1 /* Read and manage MIPS symbol tables from object modules.
2 Source originally from hartzell@boulder.colorado.edu
3 Rewritten by: meissner@osf.org
4 Copyright (C) 1991 Free Software Foundation, Inc.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <sys/types.h>
40 #define ST_RFDESCAPE 0xfff
44 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
45 and mips-tdump.c to print them out. This is used on the Alpha,
46 which does not include mips.h.
48 These must match the corresponding definitions in gdb/mipsread.c.
49 Unfortunately, gcc and gdb do not currently share any directories. */
51 #define CODE_MASK 0x8F300
52 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
53 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
54 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
59 typedef const void *CPTR_T;
63 #if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
68 typedef char *PTR_T; /* Ultrix 3.1 */
76 #define uchar unsigned char
77 #define ushort unsigned short
78 #define uint unsigned int
79 #define ulong unsigned long
82 /* Do to size_t being defined in sys/types.h and different
83 in stddef.h, we have to do this by hand..... Note, these
84 types are correct for MIPS based systems, and may not be
85 correct for other systems. */
91 /* Redefinition of of storage classes as an enumeration for better
95 #define stStaParam 16 /* Fortran static parameters */
99 #define btVoid 26 /* void basic type */
103 sc_Nil = scNil, /* no storage class */
104 sc_Text = scText, /* text symbol */
105 sc_Data = scData, /* initialized data symbol */
106 sc_Bss = scBss, /* un-initialized data symbol */
107 sc_Register = scRegister, /* value of symbol is register number */
108 sc_Abs = scAbs, /* value of symbol is absolute */
109 sc_Undefined = scUndefined, /* who knows? */
110 sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
111 sc_Bits = scBits, /* this is a bit field */
112 sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */
113 sc_RegImage = scRegImage, /* register value saved on stack */
114 sc_Info = scInfo, /* symbol contains debugger information */
115 sc_UserStruct = scUserStruct, /* addr in struct user for current process */
116 sc_SData = scSData, /* load time only small data */
117 sc_SBss = scSBss, /* load time only small common */
118 sc_RData = scRData, /* load time only read only data */
119 sc_Var = scVar, /* Var parameter (fortran,pascal) */
120 sc_Common = scCommon, /* common variable */
121 sc_SCommon = scSCommon, /* small common */
122 sc_VarRegister = scVarRegister, /* Var parameter in a register */
123 sc_Variant = scVariant, /* Variant record */
124 sc_SUndefined = scSUndefined, /* small undefined(external) data */
125 sc_Init = scInit, /* .init section symbol */
126 sc_Max = scMax /* Max storage class+1 */
129 /* Redefinition of symbol type. */
132 st_Nil = stNil, /* Nuthin' special */
133 st_Global = stGlobal, /* external symbol */
134 st_Static = stStatic, /* static */
135 st_Param = stParam, /* procedure argument */
136 st_Local = stLocal, /* local variable */
137 st_Label = stLabel, /* label */
138 st_Proc = stProc, /* " " Procedure */
139 st_Block = stBlock, /* beginning of block */
140 st_End = stEnd, /* end (of anything) */
141 st_Member = stMember, /* member (of anything - struct/union/enum */
142 st_Typedef = stTypedef, /* type definition */
143 st_File = stFile, /* file name */
144 st_RegReloc = stRegReloc, /* register relocation */
145 st_Forward = stForward, /* forwarding address */
146 st_StaticProc = stStaticProc, /* load time only static procs */
147 st_StaParam = stStaParam, /* Fortran static parameters */
148 st_Constant = stConstant, /* const */
149 st_Str = stStr, /* string */
150 st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
151 st_Expr = stExpr, /* 2+2 vs. 4 */
152 st_Type = stType, /* post-coercion SER */
153 st_Max = stMax /* max type+1 */
156 /* Redefinition of type qualifiers. */
159 tq_Nil = tqNil, /* bt is what you see */
160 tq_Ptr = tqPtr, /* pointer */
161 tq_Proc = tqProc, /* procedure */
162 tq_Array = tqArray, /* duh */
163 tq_Far = tqFar, /* longer addressing - 8086/8 land */
164 tq_Vol = tqVol, /* volatile */
165 tq_Max = tqMax /* Max type qualifier+1 */
168 /* Redefinition of basic types. */
171 bt_Nil = btNil, /* undefined */
172 bt_Adr = btAdr, /* address - integer same size as pointer */
173 bt_Char = btChar, /* character */
174 bt_UChar = btUChar, /* unsigned character */
175 bt_Short = btShort, /* short */
176 bt_UShort = btUShort, /* unsigned short */
177 bt_Int = btInt, /* int */
178 bt_UInt = btUInt, /* unsigned int */
179 bt_Long = btLong, /* long */
180 bt_ULong = btULong, /* unsigned long */
181 bt_Float = btFloat, /* float (real) */
182 bt_Double = btDouble, /* Double (real) */
183 bt_Struct = btStruct, /* Structure (Record) */
184 bt_Union = btUnion, /* Union (variant) */
185 bt_Enum = btEnum, /* Enumerated */
186 bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
187 bt_Range = btRange, /* subrange of int */
188 bt_Set = btSet, /* pascal sets */
189 bt_Complex = btComplex, /* fortran complex */
190 bt_DComplex = btDComplex, /* fortran double complex */
191 bt_Indirect = btIndirect, /* forward or unnamed typedef */
192 bt_FixedDec = btFixedDec, /* Fixed Decimal */
193 bt_FloatDec = btFloatDec, /* Float Decimal */
194 bt_String = btString, /* Varying Length Character String */
195 bt_Bit = btBit, /* Aligned Bit String */
196 bt_Picture = btPicture, /* Picture */
197 bt_Void = btVoid, /* void */
198 bt_Max = btMax /* Max basic type+1 */
201 /* Redefinition of the language codes. */
205 lang_Pascal = langPascal,
206 lang_Fortran = langFortran,
207 lang_Assembler = langAssembler,
208 lang_Machine = langMachine,
212 lang_Cobol = langCobol
215 /* Redefinition of the debug level codes. */
217 typedef enum glevel {
225 /* Keep track of the active scopes. */
226 typedef struct scope {
227 struct scope *prev; /* previous scope */
228 ulong open_sym; /* symbol opening scope */
229 sc_t sc; /* storage class */
230 st_t st; /* symbol type */
233 struct filehdr global_hdr; /* a.out header */
235 int errors = 0; /* # of errors */
236 int want_aux = 0; /* print aux table */
237 int want_line = 0; /* print line numbers */
238 int want_rfd = 0; /* print relative file desc's */
239 int want_scope = 0; /* print scopes for every symbol */
240 int tfile = 0; /* no global header file */
241 int tfile_fd; /* file descriptor of .T file */
242 off_t tfile_offset; /* current offset in .T file */
243 scope_t *cur_scope = 0; /* list of active scopes */
244 scope_t *free_scope = 0; /* list of freed scopes */
245 HDRR sym_hdr; /* symbolic header */
246 char *l_strings; /* local strings */
247 char *e_strings; /* external strings */
248 SYMR *l_symbols; /* local symbols */
249 EXTR *e_symbols; /* external symbols */
250 LINER *lines; /* line numbers */
251 DNR *dense_nums; /* dense numbers */
252 OPTR *opt_symbols; /* optimization symbols */
253 AUXU *aux_symbols; /* Auxiliary symbols */
254 char *aux_used; /* map of which aux syms are used */
255 FDR *file_desc; /* file tables */
256 ulong *rfile_desc; /* relative file tables */
257 PDR *proc_desc; /* procedure tables */
259 /* Forward reference for functions. */
260 PTR_T read_seek __proto((PTR_T, size_t, off_t, const char *));
261 void read_tfile __proto((void));
262 void print_global_hdr __proto((struct filehdr *));
263 void print_sym_hdr __proto((HDRR *));
264 void print_file_desc __proto((FDR *, int));
265 void print_symbol __proto((SYMR *, int, char *, AUXU *, int));
266 void print_aux __proto((AUXU, int, int));
267 void emit_aggregate __proto((char *, AUXU, AUXU, const char *));
268 char *st_to_string __proto((st_t));
269 char *sc_to_string __proto((sc_t));
270 char *glevel_to_string __proto((glevel_t));
271 char *lang_to_string __proto((lang_t));
272 char *type_to_string __proto((AUXU *, int));
275 extern PTR_T malloc __proto((size_t));
276 extern PTR_T calloc __proto((size_t, size_t));
277 extern PTR_T realloc __proto((PTR_T, size_t));
278 extern void free __proto((PTR_T));
280 extern char *ctime __proto((time_t *));
286 /* Create a table of debugging stab-codes and corresponding names. */
288 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
289 struct {short code; char string[10];} stab_names[] = {
295 /* Read some bytes at a specified location, and return a pointer. */
298 read_seek (ptr, size, offset, context)
299 PTR_T ptr; /* pointer to buffer or NULL */
300 size_t size; /* # bytes to read */
301 off_t offset; /* offset to read at */
302 const char *context; /* context for error message */
306 if (size == 0) /* nothing to read */
309 if ((ptr == (PTR_T)0 && (ptr = malloc (size)) == (PTR_T)0)
310 || (tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
311 || (read_size = read (tfile_fd, ptr, size)) < 0)
317 if (read_size != size)
319 fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
320 context, read_size, (long) size);
324 tfile_offset = offset + size;
329 /* Convert language code to string format. */
332 lang_to_string (lang)
337 case langC: return "C";
338 case langPascal: return "Pascal";
339 case langFortran: return "Fortran";
340 case langAssembler: return "Assembler";
341 case langMachine: return "Machine";
342 case langNil: return "Nil";
343 case langAda: return "Ada";
344 case langPl1: return "Pl1";
345 case langCobol: return "Cobol";
348 return "Unknown language";
352 /* Convert storage class to string. */
355 sc_to_string(storage_class)
358 switch(storage_class)
360 case sc_Nil: return "Nil";
361 case sc_Text: return "Text";
362 case sc_Data: return "Data";
363 case sc_Bss: return "Bss";
364 case sc_Register: return "Register";
365 case sc_Abs: return "Abs";
366 case sc_Undefined: return "Undefined";
367 case sc_CdbLocal: return "CdbLocal";
368 case sc_Bits: return "Bits";
369 case sc_CdbSystem: return "CdbSystem";
370 case sc_RegImage: return "RegImage";
371 case sc_Info: return "Info";
372 case sc_UserStruct: return "UserStruct";
373 case sc_SData: return "SData";
374 case sc_SBss: return "SBss";
375 case sc_RData: return "RData";
376 case sc_Var: return "Var";
377 case sc_Common: return "Common";
378 case sc_SCommon: return "SCommon";
379 case sc_VarRegister: return "VarRegister";
380 case sc_Variant: return "Variant";
381 case sc_SUndefined: return "SUndefined";
382 case sc_Init: return "Init";
383 case sc_Max: return "Max";
390 /* Convert symbol type to string. */
393 st_to_string(symbol_type)
398 case st_Nil: return "Nil";
399 case st_Global: return "Global";
400 case st_Static: return "Static";
401 case st_Param: return "Param";
402 case st_Local: return "Local";
403 case st_Label: return "Label";
404 case st_Proc: return "Proc";
405 case st_Block: return "Block";
406 case st_End: return "End";
407 case st_Member: return "Member";
408 case st_Typedef: return "Typedef";
409 case st_File: return "File";
410 case st_RegReloc: return "RegReloc";
411 case st_Forward: return "Forward";
412 case st_StaticProc: return "StaticProc";
413 case st_Constant: return "Constant";
414 case st_StaParam: return "StaticParam";
415 case st_Str: return "String";
416 case st_Number: return "Number";
417 case st_Expr: return "Expr";
418 case st_Type: return "Type";
419 case st_Max: return "Max";
426 /* Convert debug level to string. */
429 glevel_to_string (g_level)
434 case GLEVEL_0: return "G0";
435 case GLEVEL_1: return "G1";
436 case GLEVEL_2: return "G2";
437 case GLEVEL_3: return "G3";
444 /* Convert the type information to string format. */
447 type_to_string (aux_ptr, index)
461 static char buffer1[1024];
462 static char buffer2[1024];
465 char *used_ptr = aux_used + (aux_ptr - aux_symbols);
467 for (i = 0; i < 7; i++)
469 qualifiers[i].low_bound = 0;
470 qualifiers[i].high_bound = 0;
471 qualifiers[i].stride = 0;
475 u = aux_ptr[index++];
477 return "-1 (no type)";
479 basic_type = (bt_t) u.ti.bt;
480 qualifiers[0].type = (tq_t) u.ti.tq0;
481 qualifiers[1].type = (tq_t) u.ti.tq1;
482 qualifiers[2].type = (tq_t) u.ti.tq2;
483 qualifiers[3].type = (tq_t) u.ti.tq3;
484 qualifiers[4].type = (tq_t) u.ti.tq4;
485 qualifiers[5].type = (tq_t) u.ti.tq5;
486 qualifiers[6].type = tq_Nil;
489 * Go get the basic type.
493 case bt_Nil: /* undefined */
497 case bt_Adr: /* address - integer same size as pointer */
498 strcpy (p1, "address");
501 case bt_Char: /* character */
505 case bt_UChar: /* unsigned character */
506 strcpy (p1, "unsigned char");
509 case bt_Short: /* short */
510 strcpy (p1, "short");
513 case bt_UShort: /* unsigned short */
514 strcpy (p1, "unsigned short");
517 case bt_Int: /* int */
521 case bt_UInt: /* unsigned int */
522 strcpy (p1, "unsigned int");
525 case bt_Long: /* long */
529 case bt_ULong: /* unsigned long */
530 strcpy (p1, "unsigned long");
533 case bt_Float: /* float (real) */
534 strcpy (p1, "float");
537 case bt_Double: /* Double (real) */
538 strcpy (p1, "double");
541 /* Structures add 1-2 aux words:
542 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
543 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
545 case bt_Struct: /* Structure (Record) */
546 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct");
548 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
549 used_ptr[++index] = 1;
551 index++; /* skip aux words */
554 /* Unions add 1-2 aux words:
555 1st word is [ST_RFDESCAPE, offset] pointer to union def;
556 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
558 case bt_Union: /* Union */
559 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union");
561 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
562 used_ptr[++index] = 1;
564 index++; /* skip aux words */
567 /* Enumerations add 1-2 aux words:
568 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
569 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
571 case bt_Enum: /* Enumeration */
572 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum");
574 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
575 used_ptr[++index] = 1;
577 index++; /* skip aux words */
580 case bt_Typedef: /* defined via a typedef, isymRef points */
581 strcpy (p1, "typedef");
584 case bt_Range: /* subrange of int */
585 strcpy (p1, "subrange");
588 case bt_Set: /* pascal sets */
592 case bt_Complex: /* fortran complex */
593 strcpy (p1, "complex");
596 case bt_DComplex: /* fortran double complex */
597 strcpy (p1, "double complex");
600 case bt_Indirect: /* forward or unnamed typedef */
601 strcpy (p1, "forward/unamed typedef");
604 case bt_FixedDec: /* Fixed Decimal */
605 strcpy (p1, "fixed decimal");
608 case bt_FloatDec: /* Float Decimal */
609 strcpy (p1, "float decimal");
612 case bt_String: /* Varying Length Character String */
613 strcpy (p1, "string");
616 case bt_Bit: /* Aligned Bit String */
620 case bt_Picture: /* Picture */
621 strcpy (p1, "picture");
624 case bt_Void: /* Void */
629 sprintf (p1, "Unknown basic type %d", (int) basic_type);
633 p1 += strlen (buffer1);
636 * If this is a bitfield, get the bitsize.
643 bitsize = aux_ptr[index++].width;
644 sprintf (p1, " : %d", bitsize);
645 p1 += strlen (buffer1);
650 * Deal with any qualifiers.
652 if (qualifiers[0].type != tq_Nil)
655 * Snarf up any array bounds in the correct order. Arrays
656 * store 5 successive words in the aux. table:
657 * word 0 RNDXR to type of the bounds (ie, int)
658 * word 1 Current file descriptor index
660 * word 3 high bound (or -1 if [])
661 * word 4 stride size in bits
663 for (i = 0; i < 7; i++)
665 if (qualifiers[i].type == tq_Array)
667 qualifiers[i].low_bound = aux_ptr[index+2].dnLow;
668 qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
669 qualifiers[i].stride = aux_ptr[index+4].width;
671 used_ptr[index+1] = 1;
672 used_ptr[index+2] = 1;
673 used_ptr[index+3] = 1;
674 used_ptr[index+4] = 1;
680 * Now print out the qualifiers.
682 for (i = 0; i < 6; i++)
684 switch (qualifiers[i].type)
691 strcpy (p2, "ptr to ");
692 p2 += sizeof ("ptr to ")-1;
696 strcpy (p2, "volatile ");
697 p2 += sizeof ("volatile ")-1;
702 p2 += sizeof ("far ")-1;
706 strcpy (p2, "func. ret. ");
707 p2 += sizeof ("func. ret. ");
715 /* Print array bounds reversed (ie, in the order the C
716 programmer writes them). C is such a fun language.... */
718 while (i < 5 && qualifiers[i+1].type == tq_Array)
721 for (j = i; j >= first_array; j--)
723 strcpy (p2, "array [");
724 p2 += sizeof ("array [")-1;
725 if (qualifiers[j].low_bound != 0)
727 "%ld:%ld {%ld bits}",
728 (long) qualifiers[j].low_bound,
729 (long) qualifiers[j].high_bound,
730 (long) qualifiers[j].stride);
732 else if (qualifiers[j].high_bound != -1)
735 (long) (qualifiers[j].high_bound + 1),
736 (long) (qualifiers[j].stride));
739 sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
742 strcpy (p2, "] of ");
743 p2 += sizeof ("] of ")-1;
751 strcpy (p2, buffer1);
756 /* Print out the global file header for object files. */
759 print_global_hdr (ptr)
762 char *time = ctime ((off_t *)&ptr->f_timdat);
763 ushort flags = ptr->f_flags;
765 printf("Global file header:\n");
766 printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic);
767 printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns);
768 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time);
769 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr);
770 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms);
771 printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr);
772 printf(" %-*s 0x%lx", 24, "flags", (ushort) flags);
774 if ((flags & F_RELFLG) != 0)
775 printf (", F_RELFLG");
777 if ((flags & F_EXEC) != 0)
780 if ((flags & F_LNNO) != 0)
783 if ((flags & F_LSYMS) != 0)
784 printf (", F_LSYMS");
786 if ((flags & F_MINMAL) != 0)
787 printf (", F_MINMAL");
789 if ((flags & F_UPDATE) != 0)
790 printf (", F_UPDATE");
792 if ((flags & F_SWABD) != 0)
793 printf (", F_SWABD");
795 if ((flags & F_AR16WR) != 0)
796 printf (", F_AR16WR");
798 if ((flags & F_AR32WR) != 0)
799 printf (", F_AR32WR");
801 if ((flags & F_AR32W) != 0)
802 printf (", F_AR32W");
804 if ((flags & F_PATCH) != 0)
805 printf (", F_PATCH/F_NODF");
811 /* Print out the symbolic header. */
814 print_sym_hdr (sym_ptr)
819 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
820 sym_ptr->magic & 0xffff,
821 (sym_ptr->vstamp & 0xffff) >> 8,
822 sym_ptr->vstamp & 0xff);
824 printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
825 printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
827 printf(" %-*s %11ld %11d %11d [%d]\n", width, "Line numbers",
828 (long)sym_ptr->cbLineOffset,
829 (long)sym_ptr->cbLine,
830 (long)sym_ptr->cbLine,
831 (int)sym_ptr->ilineMax);
833 printf(" %-*s %11ld %11d %11d\n", width, "Dense numbers",
834 (long)sym_ptr->cbDnOffset,
835 (long)sym_ptr->idnMax,
836 (long)(sym_ptr->idnMax * sizeof (DNR)));
838 printf(" %-*s %11ld %11d %11d\n", width, "Procedures Tables",
839 (long)sym_ptr->cbPdOffset,
840 (long)sym_ptr->ipdMax,
841 (long)(sym_ptr->ipdMax * sizeof (PDR)));
843 printf(" %-*s %11ld %11d %11d\n", width, "Local Symbols",
844 (long)sym_ptr->cbSymOffset,
845 (long)sym_ptr->isymMax,
846 (long)(sym_ptr->isymMax * sizeof (SYMR)));
848 printf(" %-*s %11ld %11d %11d\n", width, "Optimization Symbols",
849 (long)sym_ptr->cbOptOffset,
850 (long)sym_ptr->ioptMax,
851 (long)(sym_ptr->ioptMax * sizeof (OPTR)));
853 printf(" %-*s %11ld %11d %11d\n", width, "Auxiliary Symbols",
854 (long)sym_ptr->cbAuxOffset,
855 (long)sym_ptr->iauxMax,
856 (long)(sym_ptr->iauxMax * sizeof (AUXU)));
858 printf(" %-*s %11ld %11d %11d\n", width, "Local Strings",
859 (long)sym_ptr->cbSsOffset,
860 (long)sym_ptr->issMax,
861 (long)sym_ptr->issMax);
863 printf(" %-*s %11ld %11d %11d\n", width, "External Strings",
864 (long)sym_ptr->cbSsExtOffset,
865 (long)sym_ptr->issExtMax,
866 (long)sym_ptr->issExtMax);
868 printf(" %-*s %11ld %11d %11d\n", width, "File Tables",
869 (long)sym_ptr->cbFdOffset,
870 (long)sym_ptr->ifdMax,
871 (long)(sym_ptr->ifdMax * sizeof (FDR)));
873 printf(" %-*s %11ld %11d %11d\n", width, "Relative Files",
874 (long)sym_ptr->cbRfdOffset,
876 (long)(sym_ptr->crfd * sizeof (ulong)));
878 printf(" %-*s %11ld %11d %11d\n", width, "External Symbols",
879 (long)sym_ptr->cbExtOffset,
880 (long)sym_ptr->iextMax,
881 (long)(sym_ptr->iextMax * sizeof (EXTR)));
885 /* Print out a symbol. */
888 print_symbol (sym_ptr, number, strbase, aux_base, ifd)
895 sc_t storage_class = (sc_t) sym_ptr->sc;
896 st_t symbol_type = (st_t) sym_ptr->st;
897 ulong index = sym_ptr->index;
898 char *used_ptr = aux_used + (aux_base - aux_symbols);
901 printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
903 if (aux_base != (AUXU *)0 && index != indexNil)
912 printf (" End+1 symbol: %ld\n", index);
915 if (free_scope == (scope_t *)0)
916 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
919 scope_ptr = free_scope;
920 free_scope = scope_ptr->prev;
922 scope_ptr->open_sym = number;
923 scope_ptr->st = symbol_type;
924 scope_ptr->sc = storage_class;
925 scope_ptr->prev = cur_scope;
926 cur_scope = scope_ptr;
931 if (storage_class == sc_Text || storage_class == sc_Info)
932 printf (" First symbol: %ld\n", index);
936 printf (" First symbol: %ld\n", aux_base[index].isym);
941 if (cur_scope == (scope_t *)0)
942 printf (" Can't pop end scope\n");
945 scope_ptr = cur_scope;
946 cur_scope = scope_ptr->prev;
947 scope_ptr->prev = free_scope;
948 free_scope = scope_ptr;
955 if (MIPS_IS_STAB(sym_ptr))
957 else if (ifd == -1) /* local symbol */
959 used_ptr[index] = used_ptr[index+1] = 1;
960 printf (" End+1 symbol: %-7ld Type: %s\n",
961 aux_base[index].isym, type_to_string (aux_base, index+1));
963 else /* global symbol */
966 printf (" Type: %s\n",
967 type_to_string (aux_base, index));
972 if (free_scope == (scope_t *)0)
973 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
976 scope_ptr = free_scope;
977 free_scope = scope_ptr->prev;
979 scope_ptr->open_sym = number;
980 scope_ptr->st = symbol_type;
981 scope_ptr->sc = storage_class;
982 scope_ptr->prev = cur_scope;
983 cur_scope = scope_ptr;
988 if (!MIPS_IS_STAB (sym_ptr))
991 printf (" Type: %s\n",
992 type_to_string (aux_base, index));
999 printf (" Scopes: ");
1000 if (cur_scope == (scope_t *)0)
1004 for (scope_ptr = cur_scope;
1005 scope_ptr != (scope_t *)0;
1006 scope_ptr = scope_ptr->prev)
1009 if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
1011 else if (scope_ptr->st == st_File)
1013 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
1015 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
1020 printf (" %d [%s]", scope_ptr->open_sym, class);
1026 printf (" Value: %-13ld ",
1027 (long)sym_ptr->value);
1029 printf ("String index: %ld\n", (long)sym_ptr->iss);
1031 printf ("String index: %-11ld Ifd: %d\n",
1032 (long)sym_ptr->iss, ifd);
1034 printf (" Symbol type: %-11sStorage class: %-11s",
1035 st_to_string (symbol_type), sc_to_string (storage_class));
1037 if (MIPS_IS_STAB(sym_ptr))
1039 register int i = sizeof(stab_names) / sizeof(stab_names[0]);
1040 char *stab_name = "stab";
1041 short code = MIPS_UNMARK_STAB(sym_ptr->index);
1043 if (stab_names[i].code == code)
1045 stab_name = stab_names[i].string;
1048 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
1050 else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
1051 printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
1053 printf ("Index: %ld\n", (long)sym_ptr->index);
1058 /* Print out a word from the aux. table in various formats. */
1061 print_aux (u, auxi, used)
1066 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1067 (used) ? " " : "* ",
1071 (long) u.rndx.index,
1084 /* Write aggregate information to a string. */
1087 emit_aggregate (string, u, u2, which)
1093 int ifd = u.rndx.rfd;
1094 int index = u.rndx.index;
1095 int sym_base, ss_base;
1098 if (ifd == ST_RFDESCAPE)
1101 sym_base = file_desc[ifd].isymBase;
1102 ss_base = file_desc[ifd].issBase;
1104 name = (index == indexNil) ? 0 : l_symbols[index + sym_base].iss;
1106 "%s %s { ifd = %d, index = %d }",
1108 (name == 0) ? "/* no name */" : &l_strings[ ss_base + name ],
1114 /* Print out information about a file descriptor, and the symbols,
1115 procedures, and line numbers within it. */
1118 print_file_desc (fdp, number)
1128 str_base = l_strings + fdp->issBase;
1129 aux_base = aux_symbols + fdp->iauxBase;
1130 used_base = aux_used + (aux_base - aux_symbols);
1132 printf ("\nFile #%d, \"%s\"\n\n", number, str_base + fdp->rss);
1134 printf (" Name index = %-10d Readin = %s\n",
1135 (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1137 printf (" Merge = %-10s Endian = %s\n",
1138 (fdp->fMerge) ? "Yes" : "No",
1139 (fdp->fBigendian) ? "BIG" : "LITTLE");
1141 printf (" Debug level = %-10s Language = %s\n",
1142 glevel_to_string (fdp->glevel),
1143 lang_to_string((lang_t) fdp->lang));
1145 printf (" Adr = 0x%08lx\n\n", (long) fdp->adr);
1147 printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1148 printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1150 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1151 width, "Local strings",
1152 (ulong) fdp->issBase,
1155 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1157 printf(" %-*s %11lu %11u %11u %11lu\n",
1158 width, "Local symbols",
1159 (ulong) fdp->isymBase,
1161 (ulong) (fdp->csym * sizeof (SYMR)),
1162 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1164 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1165 width, "Line numbers",
1166 (ulong) fdp->cbLineOffset,
1169 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1171 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1172 width, "Optimization symbols",
1173 (ulong) fdp->ioptBase,
1175 (ulong) (fdp->copt * sizeof (OPTR)),
1176 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1178 printf(" %-*s %11llu %11lu %11lu %11lu\n",
1179 width, "Procedures",
1180 (ulong) fdp->ipdFirst,
1182 (ulong) (fdp->cpd * sizeof (PDR)),
1183 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1185 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1186 width, "Auxiliary symbols",
1187 (ulong) fdp->iauxBase,
1189 (ulong) (fdp->caux * sizeof (AUXU)),
1190 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1192 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1193 width, "Relative Files",
1194 (ulong) fdp->rfdBase,
1196 (ulong) (fdp->crfd * sizeof (ulong)),
1197 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1200 if (want_scope && cur_scope != (scope_t *)0)
1201 printf ("\n Warning scope does not start at 0!\n");
1204 * print the info about the symbol table.
1206 printf ("\n There are %lu local symbols, starting at %lu\n",
1208 (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1210 for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1211 print_symbol (&l_symbols[symi],
1212 symi - fdp->isymBase,
1217 if (want_scope && cur_scope != (scope_t *)0)
1218 printf ("\n Warning scope does not end at 0!\n");
1221 * print the aux. table if desired.
1224 if (want_aux && fdp->caux != 0)
1228 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1230 (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1232 for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1233 print_aux (aux_base[auxi], auxi, used_base[auxi]);
1237 * print the relative file descriptors.
1239 if (want_rfd && fdp->crfd != 0)
1243 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1245 (ulong) fdp->rfdBase);
1247 rfd_ptr = rfile_desc + fdp->rfdBase;
1248 for (i = 0; i < fdp->crfd; i++)
1250 printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1256 * do the procedure descriptors.
1258 printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1259 printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1261 for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1263 PDR *proc_ptr = &proc_desc[pdi];
1264 printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1266 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1267 (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1268 l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1270 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1271 (long) proc_ptr->regmask,
1272 (long) proc_ptr->regoffset,
1273 (long) proc_ptr->fregmask,
1274 (long) proc_ptr->fregoffset);
1276 printf ("\t .frame $%d,%ld,$%d\n",
1277 (int) proc_ptr->framereg,
1278 (long) proc_ptr->frameoffset,
1279 (int) proc_ptr->pcreg);
1281 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1282 (long) proc_ptr->iopt,
1283 (long) proc_ptr->isym);
1285 printf ("\t First line # = %-11ld Last line # = %ld\n",
1286 (long) proc_ptr->lnLow,
1287 (long) proc_ptr->lnHigh);
1289 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1290 (long) proc_ptr->cbLineOffset,
1291 (long) proc_ptr->adr);
1294 * print the line number entries.
1297 if (want_line && fdp->cline != 0)
1300 long cur_line = proc_ptr->lnLow;
1301 uchar *line_ptr = ((uchar *)lines) + proc_ptr->cbLineOffset;
1304 if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */
1305 line_end = ((uchar *)lines) + fdp->cbLine + fdp->ilineBase;
1306 else /* not last proc. */
1307 line_end = ((uchar *)lines) + proc_desc[pdi+1].cbLineOffset;
1310 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1311 (ulong) (line_end - line_ptr),
1312 (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1314 while (line_ptr < line_end)
1315 { /* sign extend nibble */
1316 delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1317 count = (*line_ptr & 0xf) + 1;
1322 delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1323 delta = (delta ^ 0x8000) - 0x8000;
1328 printf ("\t Line %11ld, delta %5d, count %2d\n",
1338 /* Read in the portions of the .T file that we will print out. */
1341 read_tfile __proto((void))
1344 off_t sym_hdr_offset = 0;
1346 (void) read_seek ((PTR_T) &magic, sizeof (magic), (off_t)0, "Magic number");
1349 /* Print out the global header, since this is not a T-file. */
1351 (void) read_seek ((PTR_T) &global_hdr, sizeof (global_hdr), (off_t)0,
1352 "Global file header");
1354 print_global_hdr (&global_hdr);
1356 if (global_hdr.f_symptr == 0)
1358 printf ("No symbolic header, Goodbye!\n");
1362 sym_hdr_offset = global_hdr.f_symptr;
1365 (void) read_seek ((PTR_T) &sym_hdr,
1370 print_sym_hdr (&sym_hdr);
1372 lines = (LINER *) read_seek ((PTR_T)0,
1374 sym_hdr.cbLineOffset,
1377 dense_nums = (DNR *) read_seek ((PTR_T)0,
1378 sym_hdr.idnMax * sizeof (DNR),
1382 proc_desc = (PDR *) read_seek ((PTR_T)0,
1383 sym_hdr.ipdMax * sizeof (PDR),
1385 "Procedure tables");
1387 l_symbols = (SYMR *) read_seek ((PTR_T)0,
1388 sym_hdr.isymMax * sizeof (SYMR),
1389 sym_hdr.cbSymOffset,
1392 opt_symbols = (OPTR *) read_seek ((PTR_T)0,
1393 sym_hdr.ioptMax * sizeof (OPTR),
1394 sym_hdr.cbOptOffset,
1395 "Optimization symbols");
1397 aux_symbols = (AUXU *) read_seek ((PTR_T)0,
1398 sym_hdr.iauxMax * sizeof (AUXU),
1399 sym_hdr.cbAuxOffset,
1400 "Auxiliary symbols");
1402 if (sym_hdr.iauxMax > 0)
1404 aux_used = calloc (sym_hdr.iauxMax, 1);
1405 if (aux_used == (char *)0)
1412 l_strings = (char *) read_seek ((PTR_T)0,
1415 "Local string table");
1417 e_strings = (char *) read_seek ((PTR_T)0,
1419 sym_hdr.cbSsExtOffset,
1420 "External string table");
1422 file_desc = (FDR *) read_seek ((PTR_T)0,
1423 sym_hdr.ifdMax * sizeof (FDR),
1427 rfile_desc = (ulong *) read_seek ((PTR_T)0,
1428 sym_hdr.crfd * sizeof (ulong),
1429 sym_hdr.cbRfdOffset,
1430 "Relative file tables");
1432 e_symbols = (EXTR *) read_seek ((PTR_T)0,
1433 sym_hdr.iextMax * sizeof (EXTR),
1434 sym_hdr.cbExtOffset,
1435 "External symbols");
1450 while ((opt = getopt (argc, argv, "alrst")) != EOF)
1453 default: errors++; break;
1454 case 'a': want_aux++; break; /* print aux table */
1455 case 'l': want_line++; break; /* print line numbers */
1456 case 'r': want_rfd++; break; /* print relative fd's */
1457 case 's': want_scope++; break; /* print scope info */
1458 case 't': tfile++; break; /* this is a tfile (without header), and not a .o */
1461 if (errors || optind != argc - 1)
1463 fprintf (stderr, "Calling Sequence:\n");
1464 fprintf (stderr, "\t%0 [-alrst] <object-or-T-file>\n", argv[0]);
1465 fprintf (stderr, "\n");
1466 fprintf (stderr, "switches:\n");
1467 fprintf (stderr, "\t-a Print out auxiliary table.\n");
1468 fprintf (stderr, "\t-l Print out line numbers.\n");
1469 fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1470 fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1471 fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
1476 * Open and process the input file.
1478 tfile_fd = open (argv[optind], O_RDONLY);
1481 perror (argv[optind]);
1488 * Print any global aux words if any.
1492 long last_aux_in_use;
1494 if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1496 printf ("\nGlobal auxiliary entries before first file:\n");
1497 for (i = 0; i < file_desc[0].iauxBase; i++)
1498 print_aux (aux_symbols[i], 0, aux_used[i]);
1501 if (sym_hdr.ifdMax == 0)
1502 last_aux_in_use = 0;
1505 file_desc[sym_hdr.ifdMax-1].iauxBase +
1506 file_desc[sym_hdr.ifdMax-1].caux - 1;
1508 if (last_aux_in_use < sym_hdr.iauxMax-1)
1510 printf ("\nGlobal auxiliary entries after last file:\n");
1511 for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1512 print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1517 * Print the information for each file.
1519 for (i = 0; i < sym_hdr.ifdMax; i++)
1520 print_file_desc (&file_desc[i], i);
1523 * Print the external symbols.
1525 want_scope = 0; /* scope info is meaning for extern symbols */
1526 printf ("\nThere are %lu external symbols, starting at %lu\n",
1527 (ulong) sym_hdr.iextMax,
1528 (ulong) sym_hdr.cbExtOffset);
1530 for(i = 0; i < sym_hdr.iextMax; i++)
1531 print_symbol (&e_symbols[i].asym, i, e_strings,
1532 aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1536 * Print unused aux symbols now.
1543 for (i = 0; i < sym_hdr.iauxMax; i++)
1549 printf ("\nThe following auxiliary table entries were unused:\n\n");
1553 printf (" #%-5d %11ld 0x%08lx %s\n",
1555 (long) aux_symbols[i].isym,
1556 (long) aux_symbols[i].isym,
1557 type_to_string (aux_symbols, i));
1569 fprintf (stderr, "mips-tdump internal error");
1577 fprintf(stderr, "%s\n", s);
1581 /* Same as `malloc' but report error if no memory available. */
1587 register PTR_T value = malloc (size);
1589 fatal ("Virtual memory exhausted.");