1 /* Read and manage MIPS symbol tables from object modules.
2 Copyright (C) 1991, 1994, 1995, 1997 Free Software Foundation, Inc.
3 Contributed by hartzell@boulder.colorado.edu,
4 Rewritten by meissner@osf.org.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
33 #include "mips/a.out.h"
34 #endif /* CROSS_COMPILE */
37 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
38 and mips-tdump.c to print them out. This is used on the Alpha,
39 which does not include mips.h.
41 These must match the corresponding definitions in gdb/mipsread.c.
42 Unfortunately, gcc and gdb do not currently share any directories. */
44 #define CODE_MASK 0x8F300
45 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
46 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
47 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
52 typedef const void *CPTR_T;
56 #if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
61 typedef char *PTR_T; /* Ultrix 3.1 */
69 #define uchar unsigned char
70 #define ushort unsigned short
71 #define uint unsigned int
72 #define ulong unsigned long
75 /* Do to size_t being defined in sys/types.h and different
76 in stddef.h, we have to do this by hand..... Note, these
77 types are correct for MIPS based systems, and may not be
78 correct for other systems. */
84 /* Redefinition of storage classes as an enumeration for better
88 #define stStaParam 16 /* Fortran static parameters */
92 #define btVoid 26 /* void basic type */
96 sc_Nil = scNil, /* no storage class */
97 sc_Text = scText, /* text symbol */
98 sc_Data = scData, /* initialized data symbol */
99 sc_Bss = scBss, /* un-initialized data symbol */
100 sc_Register = scRegister, /* value of symbol is register number */
101 sc_Abs = scAbs, /* value of symbol is absolute */
102 sc_Undefined = scUndefined, /* who knows? */
103 sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
104 sc_Bits = scBits, /* this is a bit field */
105 sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */
106 sc_RegImage = scRegImage, /* register value saved on stack */
107 sc_Info = scInfo, /* symbol contains debugger information */
108 sc_UserStruct = scUserStruct, /* addr in struct user for current process */
109 sc_SData = scSData, /* load time only small data */
110 sc_SBss = scSBss, /* load time only small common */
111 sc_RData = scRData, /* load time only read only data */
112 sc_Var = scVar, /* Var parameter (fortran,pascal) */
113 sc_Common = scCommon, /* common variable */
114 sc_SCommon = scSCommon, /* small common */
115 sc_VarRegister = scVarRegister, /* Var parameter in a register */
116 sc_Variant = scVariant, /* Variant record */
117 sc_SUndefined = scSUndefined, /* small undefined(external) data */
118 sc_Init = scInit, /* .init section symbol */
119 sc_Max = scMax /* Max storage class+1 */
122 /* Redefinition of symbol type. */
125 st_Nil = stNil, /* Nuthin' special */
126 st_Global = stGlobal, /* external symbol */
127 st_Static = stStatic, /* static */
128 st_Param = stParam, /* procedure argument */
129 st_Local = stLocal, /* local variable */
130 st_Label = stLabel, /* label */
131 st_Proc = stProc, /* " " Procedure */
132 st_Block = stBlock, /* beginning of block */
133 st_End = stEnd, /* end (of anything) */
134 st_Member = stMember, /* member (of anything - struct/union/enum */
135 st_Typedef = stTypedef, /* type definition */
136 st_File = stFile, /* file name */
137 st_RegReloc = stRegReloc, /* register relocation */
138 st_Forward = stForward, /* forwarding address */
139 st_StaticProc = stStaticProc, /* load time only static procs */
140 st_StaParam = stStaParam, /* Fortran static parameters */
141 st_Constant = stConstant, /* const */
143 st_Struct = stStruct, /* struct */
144 st_Union = stUnion, /* union */
145 st_Enum = stEnum, /* enum */
147 st_Str = stStr, /* string */
148 st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
149 st_Expr = stExpr, /* 2+2 vs. 4 */
150 st_Type = stType, /* post-coercion SER */
151 st_Max = stMax /* max type+1 */
154 /* Redefinition of type qualifiers. */
157 tq_Nil = tqNil, /* bt is what you see */
158 tq_Ptr = tqPtr, /* pointer */
159 tq_Proc = tqProc, /* procedure */
160 tq_Array = tqArray, /* duh */
161 tq_Far = tqFar, /* longer addressing - 8086/8 land */
162 tq_Vol = tqVol, /* volatile */
163 tq_Max = tqMax /* Max type qualifier+1 */
166 /* Redefinition of basic types. */
169 bt_Nil = btNil, /* undefined */
170 bt_Adr = btAdr, /* address - integer same size as pointer */
171 bt_Char = btChar, /* character */
172 bt_UChar = btUChar, /* unsigned character */
173 bt_Short = btShort, /* short */
174 bt_UShort = btUShort, /* unsigned short */
175 bt_Int = btInt, /* int */
176 bt_UInt = btUInt, /* unsigned int */
177 bt_Long = btLong, /* long */
178 bt_ULong = btULong, /* unsigned long */
179 bt_Float = btFloat, /* float (real) */
180 bt_Double = btDouble, /* Double (real) */
181 bt_Struct = btStruct, /* Structure (Record) */
182 bt_Union = btUnion, /* Union (variant) */
183 bt_Enum = btEnum, /* Enumerated */
184 bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
185 bt_Range = btRange, /* subrange of int */
186 bt_Set = btSet, /* pascal sets */
187 bt_Complex = btComplex, /* fortran complex */
188 bt_DComplex = btDComplex, /* fortran double complex */
189 bt_Indirect = btIndirect, /* forward or unnamed typedef */
190 bt_FixedDec = btFixedDec, /* Fixed Decimal */
191 bt_FloatDec = btFloatDec, /* Float Decimal */
192 bt_String = btString, /* Varying Length Character String */
193 bt_Bit = btBit, /* Aligned Bit String */
194 bt_Picture = btPicture, /* Picture */
195 bt_Void = btVoid, /* void */
196 bt_Max = btMax /* Max basic type+1 */
199 /* Redefinition of the language codes. */
203 lang_Pascal = langPascal,
204 lang_Fortran = langFortran,
205 lang_Assembler = langAssembler,
206 lang_Machine = langMachine,
210 lang_Cobol = langCobol
213 /* Redefinition of the debug level codes. */
215 typedef enum glevel {
223 /* Keep track of the active scopes. */
224 typedef struct scope {
225 struct scope *prev; /* previous scope */
226 ulong open_sym; /* symbol opening scope */
227 sc_t sc; /* storage class */
228 st_t st; /* symbol type */
231 struct filehdr global_hdr; /* a.out header */
233 int errors = 0; /* # of errors */
234 int want_aux = 0; /* print aux table */
235 int want_line = 0; /* print line numbers */
236 int want_rfd = 0; /* print relative file desc's */
237 int want_scope = 0; /* print scopes for every symbol */
238 int tfile = 0; /* no global header file */
239 int tfile_fd; /* file descriptor of .T file */
240 off_t tfile_offset; /* current offset in .T file */
241 scope_t *cur_scope = 0; /* list of active scopes */
242 scope_t *free_scope = 0; /* list of freed scopes */
243 HDRR sym_hdr; /* symbolic header */
244 char *l_strings; /* local strings */
245 char *e_strings; /* external strings */
246 SYMR *l_symbols; /* local symbols */
247 EXTR *e_symbols; /* external symbols */
248 LINER *lines; /* line numbers */
249 DNR *dense_nums; /* dense numbers */
250 OPTR *opt_symbols; /* optimization symbols */
251 AUXU *aux_symbols; /* Auxiliary symbols */
252 char *aux_used; /* map of which aux syms are used */
253 FDR *file_desc; /* file tables */
254 ulong *rfile_desc; /* relative file tables */
255 PDR *proc_desc; /* procedure tables */
257 /* Forward reference for functions. */
258 PTR_T read_seek __proto((PTR_T, size_t, off_t, const char *));
259 void read_tfile __proto((void));
260 void print_global_hdr __proto((struct filehdr *));
261 void print_sym_hdr __proto((HDRR *));
262 void print_file_desc __proto((FDR *, int));
263 void print_symbol __proto((SYMR *, int, char *, AUXU *, int, FDR *));
264 void print_aux __proto((AUXU, int, int));
265 void emit_aggregate __proto((char *, AUXU, AUXU, const char *, FDR *));
266 char *st_to_string __proto((st_t));
267 char *sc_to_string __proto((sc_t));
268 char *glevel_to_string __proto((glevel_t));
269 char *lang_to_string __proto((lang_t));
270 char *type_to_string __proto((AUXU *, int, FDR *));
273 extern PTR_T malloc __proto((size_t));
274 extern PTR_T calloc __proto((size_t, size_t));
275 extern PTR_T realloc __proto((PTR_T, size_t));
276 extern void free __proto((PTR_T));
283 /* Create a table of debugging stab-codes and corresponding names. */
285 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
286 struct {short code; char string[10];} stab_names[] = {
292 /* Read some bytes at a specified location, and return a pointer. */
295 read_seek (ptr, size, offset, context)
296 PTR_T ptr; /* pointer to buffer or NULL */
297 size_t size; /* # bytes to read */
298 off_t offset; /* offset to read at */
299 const char *context; /* context for error message */
303 if (size == 0) /* nothing to read */
306 if ((ptr == (PTR_T) 0 && (ptr = malloc (size)) == (PTR_T) 0)
307 || (tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
308 || (read_size = read (tfile_fd, ptr, size)) < 0)
314 if (read_size != size)
316 fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
317 context, read_size, (long) size);
321 tfile_offset = offset + size;
326 /* Convert language code to string format. */
329 lang_to_string (lang)
334 case langC: return "C";
335 case langPascal: return "Pascal";
336 case langFortran: return "Fortran";
337 case langAssembler: return "Assembler";
338 case langMachine: return "Machine";
339 case langNil: return "Nil";
340 case langAda: return "Ada";
341 case langPl1: return "Pl1";
342 case langCobol: return "Cobol";
345 return "Unknown language";
349 /* Convert storage class to string. */
352 sc_to_string(storage_class)
355 switch(storage_class)
357 case sc_Nil: return "Nil";
358 case sc_Text: return "Text";
359 case sc_Data: return "Data";
360 case sc_Bss: return "Bss";
361 case sc_Register: return "Register";
362 case sc_Abs: return "Abs";
363 case sc_Undefined: return "Undefined";
364 case sc_CdbLocal: return "CdbLocal";
365 case sc_Bits: return "Bits";
366 case sc_CdbSystem: return "CdbSystem";
367 case sc_RegImage: return "RegImage";
368 case sc_Info: return "Info";
369 case sc_UserStruct: return "UserStruct";
370 case sc_SData: return "SData";
371 case sc_SBss: return "SBss";
372 case sc_RData: return "RData";
373 case sc_Var: return "Var";
374 case sc_Common: return "Common";
375 case sc_SCommon: return "SCommon";
376 case sc_VarRegister: return "VarRegister";
377 case sc_Variant: return "Variant";
378 case sc_SUndefined: return "SUndefined";
379 case sc_Init: return "Init";
380 case sc_Max: return "Max";
387 /* Convert symbol type to string. */
390 st_to_string(symbol_type)
395 case st_Nil: return "Nil";
396 case st_Global: return "Global";
397 case st_Static: return "Static";
398 case st_Param: return "Param";
399 case st_Local: return "Local";
400 case st_Label: return "Label";
401 case st_Proc: return "Proc";
402 case st_Block: return "Block";
403 case st_End: return "End";
404 case st_Member: return "Member";
405 case st_Typedef: return "Typedef";
406 case st_File: return "File";
407 case st_RegReloc: return "RegReloc";
408 case st_Forward: return "Forward";
409 case st_StaticProc: return "StaticProc";
410 case st_Constant: return "Constant";
411 case st_StaParam: return "StaticParam";
413 case st_Struct: return "Struct";
414 case st_Union: return "Union";
415 case st_Enum: return "Enum";
417 case st_Str: return "String";
418 case st_Number: return "Number";
419 case st_Expr: return "Expr";
420 case st_Type: return "Type";
421 case st_Max: return "Max";
428 /* Convert debug level to string. */
431 glevel_to_string (g_level)
436 case GLEVEL_0: return "G0";
437 case GLEVEL_1: return "G1";
438 case GLEVEL_2: return "G2";
439 case GLEVEL_3: return "G3";
446 /* Convert the type information to string format. */
449 type_to_string (aux_ptr, index, fdp)
464 static char buffer1[1024];
465 static char buffer2[1024];
468 char *used_ptr = aux_used + (aux_ptr - aux_symbols);
470 for (i = 0; i < 7; i++)
472 qualifiers[i].low_bound = 0;
473 qualifiers[i].high_bound = 0;
474 qualifiers[i].stride = 0;
478 u = aux_ptr[index++];
480 return "-1 (no type)";
482 basic_type = (bt_t) u.ti.bt;
483 qualifiers[0].type = (tq_t) u.ti.tq0;
484 qualifiers[1].type = (tq_t) u.ti.tq1;
485 qualifiers[2].type = (tq_t) u.ti.tq2;
486 qualifiers[3].type = (tq_t) u.ti.tq3;
487 qualifiers[4].type = (tq_t) u.ti.tq4;
488 qualifiers[5].type = (tq_t) u.ti.tq5;
489 qualifiers[6].type = tq_Nil;
492 * Go get the basic type.
496 case bt_Nil: /* undefined */
500 case bt_Adr: /* address - integer same size as pointer */
501 strcpy (p1, "address");
504 case bt_Char: /* character */
508 case bt_UChar: /* unsigned character */
509 strcpy (p1, "unsigned char");
512 case bt_Short: /* short */
513 strcpy (p1, "short");
516 case bt_UShort: /* unsigned short */
517 strcpy (p1, "unsigned short");
520 case bt_Int: /* int */
524 case bt_UInt: /* unsigned int */
525 strcpy (p1, "unsigned int");
528 case bt_Long: /* long */
532 case bt_ULong: /* unsigned long */
533 strcpy (p1, "unsigned long");
536 case bt_Float: /* float (real) */
537 strcpy (p1, "float");
540 case bt_Double: /* Double (real) */
541 strcpy (p1, "double");
544 /* Structures add 1-2 aux words:
545 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
546 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
548 case bt_Struct: /* Structure (Record) */
549 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp);
551 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
552 used_ptr[++index] = 1;
554 index++; /* skip aux words */
557 /* Unions add 1-2 aux words:
558 1st word is [ST_RFDESCAPE, offset] pointer to union def;
559 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
561 case bt_Union: /* Union */
562 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp);
564 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
565 used_ptr[++index] = 1;
567 index++; /* skip aux words */
570 /* Enumerations add 1-2 aux words:
571 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
572 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
574 case bt_Enum: /* Enumeration */
575 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp);
577 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
578 used_ptr[++index] = 1;
580 index++; /* skip aux words */
583 case bt_Typedef: /* defined via a typedef, isymRef points */
584 strcpy (p1, "typedef");
587 case bt_Range: /* subrange of int */
588 strcpy (p1, "subrange");
591 case bt_Set: /* pascal sets */
595 case bt_Complex: /* fortran complex */
596 strcpy (p1, "complex");
599 case bt_DComplex: /* fortran double complex */
600 strcpy (p1, "double complex");
603 case bt_Indirect: /* forward or unnamed typedef */
604 strcpy (p1, "forward/unnamed typedef");
607 case bt_FixedDec: /* Fixed Decimal */
608 strcpy (p1, "fixed decimal");
611 case bt_FloatDec: /* Float Decimal */
612 strcpy (p1, "float decimal");
615 case bt_String: /* Varying Length Character String */
616 strcpy (p1, "string");
619 case bt_Bit: /* Aligned Bit String */
623 case bt_Picture: /* Picture */
624 strcpy (p1, "picture");
627 case bt_Void: /* Void */
632 sprintf (p1, "Unknown basic type %d", (int) basic_type);
636 p1 += strlen (buffer1);
639 * If this is a bitfield, get the bitsize.
646 bitsize = aux_ptr[index++].width;
647 sprintf (p1, " : %d", bitsize);
648 p1 += strlen (buffer1);
653 * Deal with any qualifiers.
655 if (qualifiers[0].type != tq_Nil)
658 * Snarf up any array bounds in the correct order. Arrays
659 * store 5 successive words in the aux. table:
660 * word 0 RNDXR to type of the bounds (ie, int)
661 * word 1 Current file descriptor index
663 * word 3 high bound (or -1 if [])
664 * word 4 stride size in bits
666 for (i = 0; i < 7; i++)
668 if (qualifiers[i].type == tq_Array)
670 qualifiers[i].low_bound = aux_ptr[index+2].dnLow;
671 qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
672 qualifiers[i].stride = aux_ptr[index+4].width;
674 used_ptr[index+1] = 1;
675 used_ptr[index+2] = 1;
676 used_ptr[index+3] = 1;
677 used_ptr[index+4] = 1;
683 * Now print out the qualifiers.
685 for (i = 0; i < 6; i++)
687 switch (qualifiers[i].type)
694 strcpy (p2, "ptr to ");
695 p2 += sizeof ("ptr to ")-1;
699 strcpy (p2, "volatile ");
700 p2 += sizeof ("volatile ")-1;
705 p2 += sizeof ("far ")-1;
709 strcpy (p2, "func. ret. ");
710 p2 += sizeof ("func. ret. ");
718 /* Print array bounds reversed (ie, in the order the C
719 programmer writes them). C is such a fun language.... */
721 while (i < 5 && qualifiers[i+1].type == tq_Array)
724 for (j = i; j >= first_array; j--)
726 strcpy (p2, "array [");
727 p2 += sizeof ("array [")-1;
728 if (qualifiers[j].low_bound != 0)
730 "%ld:%ld {%ld bits}",
731 (long) qualifiers[j].low_bound,
732 (long) qualifiers[j].high_bound,
733 (long) qualifiers[j].stride);
735 else if (qualifiers[j].high_bound != -1)
738 (long) (qualifiers[j].high_bound + 1),
739 (long) (qualifiers[j].stride));
742 sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
745 strcpy (p2, "] of ");
746 p2 += sizeof ("] of ")-1;
754 strcpy (p2, buffer1);
759 /* Print out the global file header for object files. */
762 print_global_hdr (ptr)
765 char *time = ctime ((time_t *)&ptr->f_timdat);
766 ushort flags = ptr->f_flags;
768 printf("Global file header:\n");
769 printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic);
770 printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns);
771 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time);
772 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr);
773 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms);
774 printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr);
775 printf(" %-*s 0x%x", 24, "flags", (ushort) flags);
777 if ((flags & F_RELFLG) != 0)
778 printf (", F_RELFLG");
780 if ((flags & F_EXEC) != 0)
783 if ((flags & F_LNNO) != 0)
786 if ((flags & F_LSYMS) != 0)
787 printf (", F_LSYMS");
789 if ((flags & F_MINMAL) != 0)
790 printf (", F_MINMAL");
792 if ((flags & F_UPDATE) != 0)
793 printf (", F_UPDATE");
795 if ((flags & F_SWABD) != 0)
796 printf (", F_SWABD");
798 if ((flags & F_AR16WR) != 0)
799 printf (", F_AR16WR");
801 if ((flags & F_AR32WR) != 0)
802 printf (", F_AR32WR");
804 if ((flags & F_AR32W) != 0)
805 printf (", F_AR32W");
807 if ((flags & F_PATCH) != 0)
808 printf (", F_PATCH/F_NODF");
814 /* Print out the symbolic header. */
817 print_sym_hdr (sym_ptr)
822 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
823 sym_ptr->magic & 0xffff,
824 (sym_ptr->vstamp & 0xffff) >> 8,
825 sym_ptr->vstamp & 0xff);
827 printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
828 printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
830 printf(" %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
831 (long) sym_ptr->cbLineOffset,
832 (long) sym_ptr->cbLine,
833 (long) sym_ptr->cbLine,
834 (int) sym_ptr->ilineMax);
836 printf(" %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
837 (long) sym_ptr->cbDnOffset,
838 (long) sym_ptr->idnMax,
839 (long) (sym_ptr->idnMax * sizeof (DNR)));
841 printf(" %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
842 (long) sym_ptr->cbPdOffset,
843 (long) sym_ptr->ipdMax,
844 (long) (sym_ptr->ipdMax * sizeof (PDR)));
846 printf(" %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
847 (long) sym_ptr->cbSymOffset,
848 (long) sym_ptr->isymMax,
849 (long) (sym_ptr->isymMax * sizeof (SYMR)));
851 printf(" %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
852 (long) sym_ptr->cbOptOffset,
853 (long) sym_ptr->ioptMax,
854 (long) (sym_ptr->ioptMax * sizeof (OPTR)));
856 printf(" %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
857 (long) sym_ptr->cbAuxOffset,
858 (long) sym_ptr->iauxMax,
859 (long) (sym_ptr->iauxMax * sizeof (AUXU)));
861 printf(" %-*s %11ld %11ld %11ld\n", width, "Local Strings",
862 (long) sym_ptr->cbSsOffset,
863 (long) sym_ptr->issMax,
864 (long) sym_ptr->issMax);
866 printf(" %-*s %11ld %11ld %11ld\n", width, "External Strings",
867 (long) sym_ptr->cbSsExtOffset,
868 (long) sym_ptr->issExtMax,
869 (long) sym_ptr->issExtMax);
871 printf(" %-*s %11ld %11ld %11ld\n", width, "File Tables",
872 (long) sym_ptr->cbFdOffset,
873 (long) sym_ptr->ifdMax,
874 (long) (sym_ptr->ifdMax * sizeof (FDR)));
876 printf(" %-*s %11ld %11ld %11ld\n", width, "Relative Files",
877 (long) sym_ptr->cbRfdOffset,
878 (long) sym_ptr->crfd,
879 (long) (sym_ptr->crfd * sizeof (ulong)));
881 printf(" %-*s %11ld %11ld %11ld\n", width, "External Symbols",
882 (long) sym_ptr->cbExtOffset,
883 (long) sym_ptr->iextMax,
884 (long) (sym_ptr->iextMax * sizeof (EXTR)));
888 /* Print out a symbol. */
891 print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
899 sc_t storage_class = (sc_t) sym_ptr->sc;
900 st_t symbol_type = (st_t) sym_ptr->st;
901 ulong index = sym_ptr->index;
902 char *used_ptr = aux_used + (aux_base - aux_symbols);
905 printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
907 if (aux_base != (AUXU *) 0 && index != indexNil)
916 printf (" End+1 symbol: %ld\n", index);
919 if (free_scope == (scope_t *) 0)
920 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
923 scope_ptr = free_scope;
924 free_scope = scope_ptr->prev;
926 scope_ptr->open_sym = number;
927 scope_ptr->st = symbol_type;
928 scope_ptr->sc = storage_class;
929 scope_ptr->prev = cur_scope;
930 cur_scope = scope_ptr;
935 if (storage_class == sc_Text || storage_class == sc_Info)
936 printf (" First symbol: %ld\n", index);
940 printf (" First symbol: %ld\n", aux_base[index].isym);
945 if (cur_scope == (scope_t *) 0)
946 printf (" Can't pop end scope\n");
949 scope_ptr = cur_scope;
950 cur_scope = scope_ptr->prev;
951 scope_ptr->prev = free_scope;
952 free_scope = scope_ptr;
959 if (MIPS_IS_STAB(sym_ptr))
961 else if (ifd == -1) /* local symbol */
963 used_ptr[index] = used_ptr[index+1] = 1;
964 printf (" End+1 symbol: %-7ld Type: %s\n",
965 aux_base[index].isym,
966 type_to_string (aux_base, index+1, fdp));
968 else /* global symbol */
969 printf (" Local symbol: %ld\n", index);
973 if (free_scope == (scope_t *) 0)
974 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
977 scope_ptr = free_scope;
978 free_scope = scope_ptr->prev;
980 scope_ptr->open_sym = number;
981 scope_ptr->st = symbol_type;
982 scope_ptr->sc = storage_class;
983 scope_ptr->prev = cur_scope;
984 cur_scope = scope_ptr;
992 printf (" End+1 symbol: %lu\n", index);
997 if (!MIPS_IS_STAB (sym_ptr))
1000 printf (" Type: %s\n",
1001 type_to_string (aux_base, index, fdp));
1008 printf (" Scopes: ");
1009 if (cur_scope == (scope_t *) 0)
1013 for (scope_ptr = cur_scope;
1014 scope_ptr != (scope_t *) 0;
1015 scope_ptr = scope_ptr->prev)
1018 if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
1020 else if (scope_ptr->st == st_File)
1022 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
1024 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
1029 printf (" %ld [%s]", scope_ptr->open_sym, class);
1035 printf (" Value: %-13ld ",
1036 (long)sym_ptr->value);
1038 printf ("String index: %ld\n", (long)sym_ptr->iss);
1040 printf ("String index: %-11ld Ifd: %d\n",
1041 (long)sym_ptr->iss, ifd);
1043 printf (" Symbol type: %-11sStorage class: %-11s",
1044 st_to_string (symbol_type), sc_to_string (storage_class));
1046 if (MIPS_IS_STAB(sym_ptr))
1048 register int i = sizeof(stab_names) / sizeof(stab_names[0]);
1049 char *stab_name = "stab";
1050 short code = MIPS_UNMARK_STAB(sym_ptr->index);
1052 if (stab_names[i].code == code)
1054 stab_name = stab_names[i].string;
1057 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
1059 else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
1060 printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
1062 printf ("Index: %ld\n", (long)sym_ptr->index);
1067 /* Print out a word from the aux. table in various formats. */
1070 print_aux (u, auxi, used)
1075 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1076 (used) ? " " : "* ",
1080 (long) u.rndx.index,
1093 /* Write aggregate information to a string. */
1096 emit_aggregate (string, u, u2, which, fdp)
1103 unsigned int ifd = u.rndx.rfd;
1104 unsigned int index = u.rndx.index;
1107 if (ifd == ST_RFDESCAPE)
1110 /* An ifd of -1 is an opaque type. An escaped index of 0 is a
1111 struct return type of a procedure compiled without -g. */
1112 if (ifd == 0xffffffff
1113 || (u.rndx.rfd == ST_RFDESCAPE && index == 0))
1114 name = "<undefined>";
1115 else if (index == indexNil)
1119 if (fdp == 0 || sym_hdr.crfd == 0)
1120 fdp = &file_desc[ifd];
1122 fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]];
1123 name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss];
1127 "%s %s { ifd = %u, index = %u }",
1128 which, name, ifd, index);
1132 /* Print out information about a file descriptor, and the symbols,
1133 procedures, and line numbers within it. */
1136 print_file_desc (fdp, number)
1146 str_base = l_strings + fdp->issBase;
1147 aux_base = aux_symbols + fdp->iauxBase;
1148 used_base = aux_used + (aux_base - aux_symbols);
1150 printf ("\nFile #%d, \"%s\"\n\n", number, str_base + fdp->rss);
1152 printf (" Name index = %-10ld Readin = %s\n",
1153 (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1155 printf (" Merge = %-10s Endian = %s\n",
1156 (fdp->fMerge) ? "Yes" : "No",
1157 (fdp->fBigendian) ? "BIG" : "LITTLE");
1159 printf (" Debug level = %-10s Language = %s\n",
1160 glevel_to_string (fdp->glevel),
1161 lang_to_string((lang_t) fdp->lang));
1163 printf (" Adr = 0x%08lx\n\n", (long) fdp->adr);
1165 printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1166 printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1168 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1169 width, "Local strings",
1170 (ulong) fdp->issBase,
1173 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1175 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1176 width, "Local symbols",
1177 (ulong) fdp->isymBase,
1179 (ulong) (fdp->csym * sizeof (SYMR)),
1180 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1182 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1183 width, "Line numbers",
1184 (ulong) fdp->cbLineOffset,
1186 (ulong) fdp->cbLine,
1187 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1189 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1190 width, "Optimization symbols",
1191 (ulong) fdp->ioptBase,
1193 (ulong) (fdp->copt * sizeof (OPTR)),
1194 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1196 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1197 width, "Procedures",
1198 (ulong) fdp->ipdFirst,
1200 (ulong) (fdp->cpd * sizeof (PDR)),
1201 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1203 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1204 width, "Auxiliary symbols",
1205 (ulong) fdp->iauxBase,
1207 (ulong) (fdp->caux * sizeof (AUXU)),
1208 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1210 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1211 width, "Relative Files",
1212 (ulong) fdp->rfdBase,
1214 (ulong) (fdp->crfd * sizeof (ulong)),
1215 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1218 if (want_scope && cur_scope != (scope_t *) 0)
1219 printf ("\n Warning scope does not start at 0!\n");
1222 * print the info about the symbol table.
1224 printf ("\n There are %lu local symbols, starting at %lu\n",
1226 (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1228 for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1229 print_symbol (&l_symbols[symi],
1230 symi - fdp->isymBase,
1236 if (want_scope && cur_scope != (scope_t *) 0)
1237 printf ("\n Warning scope does not end at 0!\n");
1240 * print the aux. table if desired.
1243 if (want_aux && fdp->caux != 0)
1247 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1249 (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1251 for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1252 print_aux (aux_base[auxi], auxi, used_base[auxi]);
1256 * print the relative file descriptors.
1258 if (want_rfd && fdp->crfd != 0)
1262 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1264 (ulong) fdp->rfdBase);
1266 rfd_ptr = rfile_desc + fdp->rfdBase;
1267 for (i = 0; i < fdp->crfd; i++)
1269 printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1275 * do the procedure descriptors.
1277 printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1278 printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1280 for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1282 PDR *proc_ptr = &proc_desc[pdi];
1283 printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1285 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1286 (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1287 l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1289 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1290 (long) proc_ptr->regmask,
1291 (long) proc_ptr->regoffset,
1292 (long) proc_ptr->fregmask,
1293 (long) proc_ptr->fregoffset);
1295 printf ("\t .frame $%d,%ld,$%d\n",
1296 (int) proc_ptr->framereg,
1297 (long) proc_ptr->frameoffset,
1298 (int) proc_ptr->pcreg);
1300 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1301 (long) proc_ptr->iopt,
1302 (long) proc_ptr->isym);
1304 printf ("\t First line # = %-11ld Last line # = %ld\n",
1305 (long) proc_ptr->lnLow,
1306 (long) proc_ptr->lnHigh);
1308 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1309 (long) proc_ptr->cbLineOffset,
1310 (long) proc_ptr->adr);
1313 * print the line number entries.
1316 if (want_line && fdp->cline != 0)
1319 long cur_line = proc_ptr->lnLow;
1320 uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset
1321 + fdp->cbLineOffset);
1324 if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */
1325 line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
1326 else /* not last proc. */
1327 line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
1328 + fdp->cbLineOffset);
1330 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1331 (ulong) (line_end - line_ptr),
1332 (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1334 while (line_ptr < line_end)
1335 { /* sign extend nibble */
1336 delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1337 count = (*line_ptr & 0xf) + 1;
1342 delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1343 delta = (delta ^ 0x8000) - 0x8000;
1348 printf ("\t Line %11ld, delta %5d, count %2d\n",
1358 /* Read in the portions of the .T file that we will print out. */
1361 read_tfile __proto((void))
1364 off_t sym_hdr_offset = 0;
1366 (void) read_seek ((PTR_T) &magic, sizeof (magic), (off_t) 0, "Magic number");
1369 /* Print out the global header, since this is not a T-file. */
1371 (void) read_seek ((PTR_T) &global_hdr, sizeof (global_hdr), (off_t) 0,
1372 "Global file header");
1374 print_global_hdr (&global_hdr);
1376 if (global_hdr.f_symptr == 0)
1378 printf ("No symbolic header, Goodbye!\n");
1382 sym_hdr_offset = global_hdr.f_symptr;
1385 (void) read_seek ((PTR_T) &sym_hdr,
1390 print_sym_hdr (&sym_hdr);
1392 lines = (LINER *) read_seek ((PTR_T) 0,
1394 sym_hdr.cbLineOffset,
1397 dense_nums = (DNR *) read_seek ((PTR_T) 0,
1398 sym_hdr.idnMax * sizeof (DNR),
1402 proc_desc = (PDR *) read_seek ((PTR_T) 0,
1403 sym_hdr.ipdMax * sizeof (PDR),
1405 "Procedure tables");
1407 l_symbols = (SYMR *) read_seek ((PTR_T) 0,
1408 sym_hdr.isymMax * sizeof (SYMR),
1409 sym_hdr.cbSymOffset,
1412 opt_symbols = (OPTR *) read_seek ((PTR_T) 0,
1413 sym_hdr.ioptMax * sizeof (OPTR),
1414 sym_hdr.cbOptOffset,
1415 "Optimization symbols");
1417 aux_symbols = (AUXU *) read_seek ((PTR_T) 0,
1418 sym_hdr.iauxMax * sizeof (AUXU),
1419 sym_hdr.cbAuxOffset,
1420 "Auxiliary symbols");
1422 if (sym_hdr.iauxMax > 0)
1424 aux_used = calloc (sym_hdr.iauxMax, 1);
1425 if (aux_used == (char *) 0)
1432 l_strings = (char *) read_seek ((PTR_T) 0,
1435 "Local string table");
1437 e_strings = (char *) read_seek ((PTR_T) 0,
1439 sym_hdr.cbSsExtOffset,
1440 "External string table");
1442 file_desc = (FDR *) read_seek ((PTR_T) 0,
1443 sym_hdr.ifdMax * sizeof (FDR),
1447 rfile_desc = (ulong *) read_seek ((PTR_T) 0,
1448 sym_hdr.crfd * sizeof (ulong),
1449 sym_hdr.cbRfdOffset,
1450 "Relative file tables");
1452 e_symbols = (EXTR *) read_seek ((PTR_T) 0,
1453 sym_hdr.iextMax * sizeof (EXTR),
1454 sym_hdr.cbExtOffset,
1455 "External symbols");
1470 while ((opt = getopt (argc, argv, "alrst")) != EOF)
1473 default: errors++; break;
1474 case 'a': want_aux++; break; /* print aux table */
1475 case 'l': want_line++; break; /* print line numbers */
1476 case 'r': want_rfd++; break; /* print relative fd's */
1477 case 's': want_scope++; break; /* print scope info */
1478 case 't': tfile++; break; /* this is a tfile (without header), and not a .o */
1481 if (errors || optind != argc - 1)
1483 fprintf (stderr, "Calling Sequence:\n");
1484 fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]);
1485 fprintf (stderr, "\n");
1486 fprintf (stderr, "switches:\n");
1487 fprintf (stderr, "\t-a Print out auxiliary table.\n");
1488 fprintf (stderr, "\t-l Print out line numbers.\n");
1489 fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1490 fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1491 fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
1496 * Open and process the input file.
1498 tfile_fd = open (argv[optind], O_RDONLY);
1501 perror (argv[optind]);
1508 * Print any global aux words if any.
1512 long last_aux_in_use;
1514 if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1516 printf ("\nGlobal auxiliary entries before first file:\n");
1517 for (i = 0; i < file_desc[0].iauxBase; i++)
1518 print_aux (aux_symbols[i], 0, aux_used[i]);
1521 if (sym_hdr.ifdMax == 0)
1522 last_aux_in_use = 0;
1525 = (file_desc[sym_hdr.ifdMax-1].iauxBase
1526 + file_desc[sym_hdr.ifdMax-1].caux - 1);
1528 if (last_aux_in_use < sym_hdr.iauxMax-1)
1530 printf ("\nGlobal auxiliary entries after last file:\n");
1531 for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1532 print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1537 * Print the information for each file.
1539 for (i = 0; i < sym_hdr.ifdMax; i++)
1540 print_file_desc (&file_desc[i], i);
1543 * Print the external symbols.
1545 want_scope = 0; /* scope info is meaning for extern symbols */
1546 printf ("\nThere are %lu external symbols, starting at %lu\n",
1547 (ulong) sym_hdr.iextMax,
1548 (ulong) sym_hdr.cbExtOffset);
1550 for(i = 0; i < sym_hdr.iextMax; i++)
1551 print_symbol (&e_symbols[i].asym, i, e_strings,
1552 aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1554 &file_desc[e_symbols[i].ifd]);
1557 * Print unused aux symbols now.
1564 for (i = 0; i < sym_hdr.iauxMax; i++)
1570 printf ("\nThe following auxiliary table entries were unused:\n\n");
1574 printf (" #%-5d %11ld 0x%08lx %s\n",
1576 (long) aux_symbols[i].isym,
1577 (long) aux_symbols[i].isym,
1578 type_to_string (aux_symbols, i, (FDR *) 0));
1590 fprintf (stderr, "mips-tdump internal error");
1598 fprintf(stderr, "%s\n", s);
1602 /* Same as `malloc' but report error if no memory available. */
1608 register PTR_T value = malloc (size);
1610 fatal ("Virtual memory exhausted.");