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>
32 typedef const void *CPTR_T;
36 #if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
41 typedef char *PTR_T; /* Ultrix 3.1 */
49 #define uchar unsigned char
50 #define ushort unsigned short
51 #define uint unsigned int
52 #define ulong unsigned long
54 /* Do to size_t being defined in sys/types.h and different
55 in stddef.h, we have to do this by hand..... Note, these
56 types are correct for MIPS based systems, and may not be
57 correct for other systems. */
63 /* Redefination of of storage classes as an enumeration for better
67 #define stStaParam 16 /* Fortran static parameters */
71 #define btVoid 26 /* void basic type */
75 sc_Nil = scNil, /* no storage class */
76 sc_Text = scText, /* text symbol */
77 sc_Data = scData, /* initialized data symbol */
78 sc_Bss = scBss, /* un-initialized data symbol */
79 sc_Register = scRegister, /* value of symbol is register number */
80 sc_Abs = scAbs, /* value of symbol is absolute */
81 sc_Undefined = scUndefined, /* who knows? */
82 sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
83 sc_Bits = scBits, /* this is a bit field */
84 sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */
85 sc_RegImage = scRegImage, /* register value saved on stack */
86 sc_Info = scInfo, /* symbol contains debugger information */
87 sc_UserStruct = scUserStruct, /* addr in struct user for current process */
88 sc_SData = scSData, /* load time only small data */
89 sc_SBss = scSBss, /* load time only small common */
90 sc_RData = scRData, /* load time only read only data */
91 sc_Var = scVar, /* Var parameter (fortran,pascal) */
92 sc_Common = scCommon, /* common variable */
93 sc_SCommon = scSCommon, /* small common */
94 sc_VarRegister = scVarRegister, /* Var parameter in a register */
95 sc_Variant = scVariant, /* Variant record */
96 sc_SUndefined = scSUndefined, /* small undefined(external) data */
97 sc_Init = scInit, /* .init section symbol */
98 sc_Max = scMax /* Max storage class+1 */
101 /* Redefinition of symbol type. */
104 st_Nil = stNil, /* Nuthin' special */
105 st_Global = stGlobal, /* external symbol */
106 st_Static = stStatic, /* static */
107 st_Param = stParam, /* procedure argument */
108 st_Local = stLocal, /* local variable */
109 st_Label = stLabel, /* label */
110 st_Proc = stProc, /* " " Procedure */
111 st_Block = stBlock, /* beginnning of block */
112 st_End = stEnd, /* end (of anything) */
113 st_Member = stMember, /* member (of anything - struct/union/enum */
114 st_Typedef = stTypedef, /* type definition */
115 st_File = stFile, /* file name */
116 st_RegReloc = stRegReloc, /* register relocation */
117 st_Forward = stForward, /* forwarding address */
118 st_StaticProc = stStaticProc, /* load time only static procs */
119 st_StaParam = stStaParam, /* Fortran static parameters */
120 st_Constant = stConstant, /* const */
121 st_Str = stStr, /* string */
122 st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
123 st_Expr = stExpr, /* 2+2 vs. 4 */
124 st_Type = stType, /* post-coersion SER */
125 st_Max = stMax /* max type+1 */
128 /* Redefinition of type qualifiers. */
131 tq_Nil = tqNil, /* bt is what you see */
132 tq_Ptr = tqPtr, /* pointer */
133 tq_Proc = tqProc, /* procedure */
134 tq_Array = tqArray, /* duh */
135 tq_Far = tqFar, /* longer addressing - 8086/8 land */
136 tq_Vol = tqVol, /* volatile */
137 tq_Max = tqMax /* Max type qualifier+1 */
140 /* Redefinition of basic types. */
143 bt_Nil = btNil, /* undefined */
144 bt_Adr = btAdr, /* address - integer same size as pointer */
145 bt_Char = btChar, /* character */
146 bt_UChar = btUChar, /* unsigned character */
147 bt_Short = btShort, /* short */
148 bt_UShort = btUShort, /* unsigned short */
149 bt_Int = btInt, /* int */
150 bt_UInt = btUInt, /* unsigned int */
151 bt_Long = btLong, /* long */
152 bt_ULong = btULong, /* unsigned long */
153 bt_Float = btFloat, /* float (real) */
154 bt_Double = btDouble, /* Double (real) */
155 bt_Struct = btStruct, /* Structure (Record) */
156 bt_Union = btUnion, /* Union (variant) */
157 bt_Enum = btEnum, /* Enumerated */
158 bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
159 bt_Range = btRange, /* subrange of int */
160 bt_Set = btSet, /* pascal sets */
161 bt_Complex = btComplex, /* fortran complex */
162 bt_DComplex = btDComplex, /* fortran double complex */
163 bt_Indirect = btIndirect, /* forward or unnamed typedef */
164 bt_FixedDec = btFixedDec, /* Fixed Decimal */
165 bt_FloatDec = btFloatDec, /* Float Decimal */
166 bt_String = btString, /* Varying Length Character String */
167 bt_Bit = btBit, /* Aligned Bit String */
168 bt_Picture = btPicture, /* Picture */
169 bt_Void = btVoid, /* void */
170 bt_Max = btMax /* Max basic type+1 */
173 /* Redefinition of the language codes. */
177 lang_Pascal = langPascal,
178 lang_Fortran = langFortran,
179 lang_Assembler = langAssembler,
180 lang_Machine = langMachine,
184 lang_Cobol = langCobol
187 /* Redefinition of the debug level codes. */
189 typedef enum glevel {
197 /* Keep track of the active scopes. */
198 typedef struct scope {
199 struct scope *prev; /* previous scope */
200 ulong open_sym; /* symbol opening scope */
201 sc_t sc; /* storage class */
202 st_t st; /* symbol type */
205 struct filehdr global_hdr; /* a.out header */
207 int errors = 0; /* # of errors */
208 int want_aux = 0; /* print aux table */
209 int want_line = 0; /* print line numbers */
210 int want_rfd = 0; /* print relative file desc's */
211 int want_scope = 0; /* print scopes for every symbol */
212 int tfile_fd; /* file descriptor of .T file */
213 off_t tfile_offset; /* current offset in .T file */
214 scope_t *cur_scope = 0; /* list of active scopes */
215 scope_t *free_scope = 0; /* list of freed scopes */
216 HDRR sym_hdr; /* symbolic header */
217 char *l_strings; /* local strings */
218 char *e_strings; /* external strings */
219 SYMR *l_symbols; /* local symbols */
220 EXTR *e_symbols; /* external symbols */
221 LINER *lines; /* line numbers */
222 DNR *dense_nums; /* dense numbers */
223 OPTR *opt_symbols; /* optimization symbols */
224 AUXU *aux_symbols; /* Auxilary symbols */
225 char *aux_used; /* map of which aux syms are used */
226 FDR *file_desc; /* file tables */
227 ulong *rfile_desc; /* relative file tables */
228 PDR *proc_desc; /* procedure tables */
230 /* Forward reference for functions. */
231 PTR_T read_seek __proto((PTR_T, size_t, off_t, const char *));
232 void read_tfile __proto((void));
233 void print_global_hdr __proto((struct filehdr *));
234 void print_sym_hdr __proto((HDRR *));
235 void print_file_desc __proto((FDR *, int));
236 void print_symbol __proto((SYMR *, int, char *, AUXU *, int));
237 void print_aux __proto((AUXU, int, int));
238 void emit_aggregate __proto((char *, AUXU, AUXU, const char *));
239 char *st_to_string __proto((st_t));
240 char *sc_to_string __proto((sc_t));
241 char *glevel_to_string __proto((glevel_t));
242 char *lang_to_string __proto((lang_t));
243 char *type_to_string __proto((AUXU *, int));
245 extern PTR_T malloc __proto((size_t));
246 extern PTR_T calloc __proto((size_t, size_t));
247 extern PTR_T realloc __proto((PTR_T, size_t));
248 extern void free __proto((PTR_T));
249 extern char *ctime __proto((time_t *));
255 /* Create a table of debugging stab-codes and corresponding names. */
257 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
258 struct {short code; char string[10];} stab_names[] = {
264 /* Read some bytes at a specified location, and return a pointer. */
267 read_seek (ptr, size, offset, context)
268 PTR_T ptr; /* pointer to buffer or NULL */
269 size_t size; /* # bytes to read */
270 off_t offset; /* offset to read at */
271 const char *context; /* context for error message */
275 if (size == 0) /* nothing to read */
278 if ((ptr == (PTR_T)0 && (ptr = malloc (size)) == (PTR_T)0)
279 || (tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
280 || (read_size = read (tfile_fd, ptr, size)) < 0)
286 if (read_size != size)
288 fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
289 context, read_size, (long) size);
293 tfile_offset = offset + size;
298 /* Convert language code to string format. */
301 lang_to_string (lang)
306 case langC: return "C";
307 case langPascal: return "Pascal";
308 case langFortran: return "Fortran";
309 case langAssembler: return "Assembler";
310 case langMachine: return "Machine";
311 case langNil: return "Nil";
312 case langAda: return "Ada";
313 case langPl1: return "Pl1";
314 case langCobol: return "Cobol";
317 return "Unknown language";
321 /* Convert storage class to string. */
324 sc_to_string(storage_class)
327 switch(storage_class)
329 case sc_Nil: return "Nil";
330 case sc_Text: return "Text";
331 case sc_Data: return "Data";
332 case sc_Bss: return "Bss";
333 case sc_Register: return "Register";
334 case sc_Abs: return "Abs";
335 case sc_Undefined: return "Undefined";
336 case sc_CdbLocal: return "CdbLocal";
337 case sc_Bits: return "Bits";
338 case sc_CdbSystem: return "CdbSystem";
339 case sc_RegImage: return "RegImage";
340 case sc_Info: return "Info";
341 case sc_UserStruct: return "UserStruct";
342 case sc_SData: return "SData";
343 case sc_SBss: return "SBss";
344 case sc_RData: return "RData";
345 case sc_Var: return "Var";
346 case sc_Common: return "Common";
347 case sc_SCommon: return "SCommon";
348 case sc_VarRegister: return "VarRegister";
349 case sc_Variant: return "Variant";
350 case sc_SUndefined: return "SUndefined";
351 case sc_Init: return "Init";
352 case sc_Max: return "Max";
359 /* Convert symbol type to string. */
362 st_to_string(symbol_type)
367 case st_Nil: return "Nil";
368 case st_Global: return "Global";
369 case st_Static: return "Static";
370 case st_Param: return "Param";
371 case st_Local: return "Local";
372 case st_Label: return "Label";
373 case st_Proc: return "Proc";
374 case st_Block: return "Block";
375 case st_End: return "End";
376 case st_Member: return "Member";
377 case st_Typedef: return "Typedef";
378 case st_File: return "File";
379 case st_RegReloc: return "RegReloc";
380 case st_Forward: return "Forward";
381 case st_StaticProc: return "StaticProc";
382 case st_Constant: return "Constant";
383 case st_StaParam: return "StaticParam";
384 case st_Str: return "String";
385 case st_Number: return "Number";
386 case st_Expr: return "Expr";
387 case st_Type: return "Type";
388 case st_Max: return "Max";
395 /* Convert debug level to string. */
398 glevel_to_string (g_level)
403 case GLEVEL_0: return "G0";
404 case GLEVEL_1: return "G1";
405 case GLEVEL_2: return "G2";
406 case GLEVEL_3: return "G3";
413 /* Convert the type information to string format. */
416 type_to_string (aux_ptr, index)
430 static char buffer1[1024];
431 static char buffer2[1024];
434 char *used_ptr = aux_used + (aux_ptr - aux_symbols);
436 for (i = 0; i < 7; i++)
438 qualifiers[i].low_bound = 0;
439 qualifiers[i].high_bound = 0;
440 qualifiers[i].stride = 0;
444 u = aux_ptr[index++];
446 return "-1 (no type)";
448 basic_type = (bt_t) u.ti.bt;
449 qualifiers[0].type = (tq_t) u.ti.tq0;
450 qualifiers[1].type = (tq_t) u.ti.tq1;
451 qualifiers[2].type = (tq_t) u.ti.tq2;
452 qualifiers[3].type = (tq_t) u.ti.tq3;
453 qualifiers[4].type = (tq_t) u.ti.tq4;
454 qualifiers[5].type = (tq_t) u.ti.tq5;
455 qualifiers[6].type = tq_Nil;
458 * Go get the basic type.
462 case bt_Nil: /* undefined */
466 case bt_Adr: /* address - integer same size as pointer */
467 strcpy (p1, "address");
470 case bt_Char: /* character */
474 case bt_UChar: /* unsigned character */
475 strcpy (p1, "unsigned char");
478 case bt_Short: /* short */
479 strcpy (p1, "short");
482 case bt_UShort: /* unsigned short */
483 strcpy (p1, "unsigned short");
486 case bt_Int: /* int */
490 case bt_UInt: /* unsigned int */
491 strcpy (p1, "unsigned int");
494 case bt_Long: /* long */
498 case bt_ULong: /* unsigned long */
499 strcpy (p1, "unsigned long");
502 case bt_Float: /* float (real) */
503 strcpy (p1, "float");
506 case bt_Double: /* Double (real) */
507 strcpy (p1, "double");
510 /* Structures add 1-2 aux words:
511 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
512 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
514 case bt_Struct: /* Structure (Record) */
515 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct");
517 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
518 used_ptr[++index] = 1;
520 index++; /* skip aux words */
523 /* Unions add 1-2 aux words:
524 1st word is [ST_RFDESCAPE, offset] pointer to union def;
525 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
527 case bt_Union: /* Union */
528 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union");
530 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
531 used_ptr[++index] = 1;
533 index++; /* skip aux words */
536 /* Enumerations add 1-2 aux words:
537 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
538 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
540 case bt_Enum: /* Enumeration */
541 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum");
543 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
544 used_ptr[++index] = 1;
546 index++; /* skip aux words */
549 case bt_Typedef: /* defined via a typedef, isymRef points */
550 strcpy (p1, "typedef");
553 case bt_Range: /* subrange of int */
554 strcpy (p1, "subrange");
557 case bt_Set: /* pascal sets */
561 case bt_Complex: /* fortran complex */
562 strcpy (p1, "complex");
565 case bt_DComplex: /* fortran double complex */
566 strcpy (p1, "double complex");
569 case bt_Indirect: /* forward or unnamed typedef */
570 strcpy (p1, "forward/unamed typedef");
573 case bt_FixedDec: /* Fixed Decimal */
574 strcpy (p1, "fixed decimal");
577 case bt_FloatDec: /* Float Decimal */
578 strcpy (p1, "float decimal");
581 case bt_String: /* Varying Length Character String */
582 strcpy (p1, "string");
585 case bt_Bit: /* Aligned Bit String */
589 case bt_Picture: /* Picture */
590 strcpy (p1, "picture");
593 case bt_Void: /* Void */
598 sprintf (p1, "Unknown basic type %d", (int) basic_type);
602 p1 += strlen (buffer1);
605 * If this is a bitfield, get the bitsize.
612 bitsize = aux_ptr[index++].width;
613 sprintf (p1, " : %d", bitsize);
614 p1 += strlen (buffer1);
619 * Deal with any qualifiers.
621 if (qualifiers[0].type != tq_Nil)
624 * Snarf up any array bounds in the correct order. Arrays
625 * store 5 succesive words in the aux. table:
626 * word 0 RNDXR to type of the bounds (ie, int)
627 * word 1 Current file descriptor index
629 * word 3 high bound (or -1 if [])
630 * word 4 stride size in bits
632 for (i = 0; i < 7; i++)
634 if (qualifiers[i].type == tq_Array)
636 qualifiers[i].low_bound = aux_ptr[index+2].dnLow;
637 qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
638 qualifiers[i].stride = aux_ptr[index+4].width;
640 used_ptr[index+1] = 1;
641 used_ptr[index+2] = 1;
642 used_ptr[index+3] = 1;
643 used_ptr[index+4] = 1;
649 * Now print out the qualifiers.
651 for (i = 0; i < 6; i++)
653 switch (qualifiers[i].type)
660 strcpy (p2, "ptr to ");
661 p2 += sizeof ("ptr to ")-1;
665 strcpy (p2, "volatile ");
666 p2 += sizeof ("volatile ")-1;
671 p2 += sizeof ("far ")-1;
675 strcpy (p2, "func. ret. ");
676 p2 += sizeof ("func. ret. ");
684 /* Print array bounds reversed (ie, in the order the C
685 programmer writes them). C is such a fun language.... */
687 while (i < 5 && qualifiers[i+1].type == tq_Array)
690 for (j = i; j >= first_array; j--)
692 strcpy (p2, "array [");
693 p2 += sizeof ("array [")-1;
694 if (qualifiers[j].low_bound != 0)
696 "%ld:%ld {%ld bits}",
697 (long) qualifiers[j].low_bound,
698 (long) qualifiers[j].high_bound,
699 (long) qualifiers[j].stride);
701 else if (qualifiers[j].high_bound != -1)
704 (long) (qualifiers[j].high_bound + 1),
705 (long) (qualifiers[j].stride));
708 sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
711 strcpy (p2, "] of ");
712 p2 += sizeof ("] of ")-1;
720 strcpy (p2, buffer1);
725 /* Print out the global file header for object files. */
728 print_global_hdr (ptr)
731 char *time = ctime ((off_t *)&ptr->f_timdat);
732 ushort flags = ptr->f_flags;
734 printf("Global file header:\n");
735 printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic);
736 printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns);
737 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time);
738 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr);
739 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms);
740 printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr);
741 printf(" %-*s 0x%lx", 24, "flags", (ushort) flags);
743 if ((flags & F_RELFLG) != 0)
744 printf (", F_RELFLG");
746 if ((flags & F_EXEC) != 0)
749 if ((flags & F_LNNO) != 0)
752 if ((flags & F_LSYMS) != 0)
753 printf (", F_LSYMS");
755 if ((flags & F_MINMAL) != 0)
756 printf (", F_MINMAL");
758 if ((flags & F_UPDATE) != 0)
759 printf (", F_UPDATE");
761 if ((flags & F_SWABD) != 0)
762 printf (", F_SWABD");
764 if ((flags & F_AR16WR) != 0)
765 printf (", F_AR16WR");
767 if ((flags & F_AR32WR) != 0)
768 printf (", F_AR32WR");
770 if ((flags & F_AR32W) != 0)
771 printf (", F_AR32W");
773 if ((flags & F_PATCH) != 0)
774 printf (", F_PATCH/F_NODF");
780 /* Print out the symbolic header. */
783 print_sym_hdr (sym_ptr)
788 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
789 sym_ptr->magic & 0xffff,
790 (sym_ptr->vstamp & 0xffff) >> 8,
791 sym_ptr->vstamp & 0xff);
793 printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
794 printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
796 printf(" %-*s %11ld %11d %11d [%d]\n", width, "Line numbers",
797 sym_ptr->cbLineOffset, sym_ptr->cbLine, sym_ptr->cbLine, sym_ptr->ilineMax);
799 printf(" %-*s %11ld %11d %11d\n", width, "Dense numbers",
800 sym_ptr->cbDnOffset, sym_ptr->idnMax, sym_ptr->idnMax * sizeof (DNR));
802 printf(" %-*s %11ld %11d %11d\n", width, "Procedures Tables",
803 sym_ptr->cbPdOffset, sym_ptr->ipdMax, sym_ptr->ipdMax * sizeof (PDR));
805 printf(" %-*s %11ld %11d %11d\n", width, "Local Symbols",
806 sym_ptr->cbSymOffset, sym_ptr->isymMax, sym_ptr->isymMax * sizeof (SYMR));
808 printf(" %-*s %11ld %11d %11d\n", width, "Optimization Symbols",
809 sym_ptr->cbOptOffset, sym_ptr->ioptMax, sym_ptr->ioptMax * sizeof (OPTR));
811 printf(" %-*s %11ld %11d %11d\n", width, "Auxilary Symbols",
812 sym_ptr->cbAuxOffset, sym_ptr->iauxMax, sym_ptr->iauxMax * sizeof (AUXU));
814 printf(" %-*s %11ld %11d %11d\n", width, "Local Strings",
815 sym_ptr->cbSsOffset, sym_ptr->issMax, sym_ptr->issMax);
817 printf(" %-*s %11ld %11d %11d\n", width, "External Strings",
818 sym_ptr->cbSsExtOffset, sym_ptr->issExtMax, sym_ptr->issExtMax);
820 printf(" %-*s %11ld %11d %11d\n", width, "File Tables",
821 sym_ptr->cbFdOffset, sym_ptr->ifdMax, sym_ptr->ifdMax * sizeof (FDR));
823 printf(" %-*s %11ld %11d %11d\n", width, "Relative Files",
824 sym_ptr->cbRfdOffset, sym_ptr->crfd, sym_ptr->crfd * sizeof (ulong));
826 printf(" %-*s %11ld %11d %11d\n", width, "External Symbols",
827 sym_ptr->cbExtOffset, sym_ptr->iextMax, sym_ptr->iextMax * sizeof (EXTR));
831 /* Print out a symbol. */
834 print_symbol (sym_ptr, number, strbase, aux_base, ifd)
841 sc_t storage_class = (sc_t) sym_ptr->sc;
842 st_t symbol_type = (st_t) sym_ptr->st;
843 ulong index = sym_ptr->index;
844 char *used_ptr = aux_used + (aux_base - aux_symbols);
847 printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
849 if (aux_base != (AUXU *)0 && index != indexNil)
858 printf (" End+1 symbol: %ld\n", index);
861 if (free_scope == (scope_t *)0)
862 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
865 scope_ptr = free_scope;
866 free_scope = scope_ptr->prev;
868 scope_ptr->open_sym = number;
869 scope_ptr->st = symbol_type;
870 scope_ptr->sc = storage_class;
871 scope_ptr->prev = cur_scope;
872 cur_scope = scope_ptr;
877 if (storage_class == sc_Text || storage_class == sc_Info)
878 printf (" First symbol: %ld\n", index);
882 printf (" First symbol: %ld\n", aux_base[index].isym);
887 if (cur_scope == (scope_t *)0)
888 printf (" Can't pop end scope\n");
891 scope_ptr = cur_scope;
892 cur_scope = scope_ptr->prev;
893 scope_ptr->prev = free_scope;
894 free_scope = scope_ptr;
901 if (MIPS_IS_STAB(sym_ptr))
903 else if (ifd == -1) /* local symbol */
905 used_ptr[index] = used_ptr[index+1] = 1;
906 printf (" End+1 symbol: %-7ld Type: %s\n",
907 aux_base[index].isym, type_to_string (aux_base, index+1));
909 else /* global symbol */
912 printf (" Type: %s\n",
913 type_to_string (aux_base, index));
918 if (free_scope == (scope_t *)0)
919 scope_ptr = (scope_t *) malloc (sizeof (scope_t));
922 scope_ptr = free_scope;
923 free_scope = scope_ptr->prev;
925 scope_ptr->open_sym = number;
926 scope_ptr->st = symbol_type;
927 scope_ptr->sc = storage_class;
928 scope_ptr->prev = cur_scope;
929 cur_scope = scope_ptr;
934 if (!MIPS_IS_STAB (sym_ptr))
937 printf (" Type: %s\n",
938 type_to_string (aux_base, index));
945 printf (" Scopes: ");
946 if (cur_scope == (scope_t *)0)
950 for (scope_ptr = cur_scope;
951 scope_ptr != (scope_t *)0;
952 scope_ptr = scope_ptr->prev)
955 if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
957 else if (scope_ptr->st == st_File)
959 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
961 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
966 printf (" %d [%s]", scope_ptr->open_sym, class);
972 printf (" Value: %-13ld ",
973 (long)sym_ptr->value);
975 printf ("String index: %ld\n", (long)sym_ptr->iss);
977 printf ("String index: %-11ld Ifd: %d\n",
978 (long)sym_ptr->iss, ifd);
980 printf (" Symbol type: %-11sStorage class: %-11s",
981 st_to_string (symbol_type), sc_to_string (storage_class));
983 if (MIPS_IS_STAB(sym_ptr))
985 register int i = sizeof(stab_names) / sizeof(stab_names[0]);
986 char *stab_name = "stab";
987 short code = MIPS_UNMARK_STAB(sym_ptr->index);
989 if (stab_names[i].code == code)
991 stab_name = stab_names[i].string;
994 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
996 else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
997 printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
999 printf ("Index: %ld\n", (long)sym_ptr->index);
1004 /* Print out a word from the aux. table in various formats. */
1007 print_aux (u, auxi, used)
1012 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1013 (used) ? " " : "* ",
1017 (long) u.rndx.index,
1030 /* Write aggregate information to a string. */
1033 emit_aggregate (string, u, u2, which)
1039 int ifd = u.rndx.rfd;
1040 int index = u.rndx.index;
1041 int sym_base, ss_base;
1044 if (ifd == ST_RFDESCAPE)
1047 sym_base = file_desc[ifd].isymBase;
1048 ss_base = file_desc[ifd].issBase;
1050 name = (index == indexNil) ? 0 : l_symbols[index + sym_base].iss;
1052 "%s %s { ifd = %d, index = %d }",
1054 (name == 0) ? "/* no name */" : &l_strings[ ss_base + name ],
1060 /* Print out information about a file descriptor, and the symbols,
1061 procedures, and line numbers within it. */
1064 print_file_desc (fdp, number)
1074 str_base = l_strings + fdp->issBase;
1075 aux_base = aux_symbols + fdp->iauxBase;
1076 used_base = aux_used + (aux_base - aux_symbols);
1078 printf ("\nFile #%d, \"%s\"\n\n", number, str_base + fdp->rss);
1080 printf (" Name index = %-10d Readin = %s\n",
1081 (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1083 printf (" Merge = %-10s Endian = %s\n",
1084 (fdp->fMerge) ? "Yes" : "No",
1085 (fdp->fBigendian) ? "BIG" : "LITTLE");
1087 printf (" Debug level = %-10s Language = %s\n",
1088 glevel_to_string (fdp->glevel),
1089 lang_to_string((lang_t) fdp->lang));
1091 printf (" Adr = 0x%08lx\n\n", (long) fdp->adr);
1093 printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1094 printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1096 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1097 width, "Local strings",
1098 (ulong) fdp->issBase,
1101 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1103 printf(" %-*s %11lu %11u %11u %11lu\n",
1104 width, "Local symbols",
1105 (ulong) fdp->isymBase,
1107 (ulong) (fdp->csym * sizeof (SYMR)),
1108 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1110 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1111 width, "Line numbers",
1112 (ulong) fdp->cbLineOffset,
1115 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1117 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1118 width, "Optimization symbols",
1119 (ulong) fdp->ioptBase,
1121 (ulong) (fdp->copt * sizeof (OPTR)),
1122 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1124 printf(" %-*s %11llu %11lu %11lu %11lu\n",
1125 width, "Procedures",
1126 (ulong) fdp->ipdFirst,
1128 (ulong) (fdp->cpd * sizeof (PDR)),
1129 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1131 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1132 width, "Auxiliary symbols",
1133 (ulong) fdp->iauxBase,
1135 (ulong) (fdp->caux * sizeof (AUXU)),
1136 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1138 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1139 width, "Relative Files",
1140 (ulong) fdp->rfdBase,
1142 (ulong) (fdp->crfd * sizeof (ulong)),
1143 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1146 if (want_scope && cur_scope != (scope_t *)0)
1147 printf ("\n Warning scope does not start at 0!\n");
1150 * print the info about the symbol table.
1152 printf ("\n There are %lu local symbols, starting at %lu\n",
1154 (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1156 for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1157 print_symbol (&l_symbols[symi],
1158 symi - fdp->isymBase,
1163 if (want_scope && cur_scope != (scope_t *)0)
1164 printf ("\n Warning scope does not end at 0!\n");
1167 * print the aux. table if desired.
1170 if (want_aux && fdp->caux != 0)
1174 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1176 (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1178 for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1179 print_aux (aux_base[auxi], auxi, used_base[auxi]);
1183 * print the relative file descriptors.
1185 if (want_rfd && fdp->crfd != 0)
1189 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1191 (ulong) fdp->rfdBase);
1193 rfd_ptr = rfile_desc + fdp->rfdBase * sizeof (ulong);
1194 for (i = 0; i < fdp->crfd; i++)
1196 printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1202 * do the procedure descriptors.
1204 printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1205 printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1207 for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1209 PDR *proc_ptr = &proc_desc[pdi];
1210 printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1212 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1213 (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1214 l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1216 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1217 (long) proc_ptr->regmask,
1218 (long) proc_ptr->regoffset,
1219 (long) proc_ptr->fregmask,
1220 (long) proc_ptr->fregoffset);
1222 printf ("\t .frame $%d,%ld,$%d\n",
1223 (int) proc_ptr->framereg,
1224 (long) proc_ptr->frameoffset,
1225 (int) proc_ptr->pcreg);
1227 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1228 (long) proc_ptr->iopt,
1229 (long) proc_ptr->isym);
1231 printf ("\t First line # = %-11ld Last line # = %ld\n",
1232 (long) proc_ptr->lnLow,
1233 (long) proc_ptr->lnHigh);
1235 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1236 (long) proc_ptr->cbLineOffset,
1237 (long) proc_ptr->adr);
1240 * print the line number entries.
1243 if (want_line && fdp->cline != 0)
1246 long cur_line = proc_ptr->lnLow;
1247 uchar *line_ptr = ((uchar *)lines) + proc_ptr->cbLineOffset;
1250 if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */
1251 line_end = ((uchar *)lines) + fdp->cbLine + fdp->ilineBase;
1252 else /* not last proc. */
1253 line_end = ((uchar *)lines) + proc_desc[pdi+1].cbLineOffset;
1256 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1257 (ulong) (line_end - line_ptr),
1258 (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1260 while (line_ptr < line_end)
1261 { /* sign extend nibble */
1262 delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1263 count = (*line_ptr & 0xf) + 1;
1268 delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1269 delta = (delta ^ 0x8000) - 0x8000;
1274 printf ("\t Line %11ld, delta %5d, count %2d\n",
1284 /* Read in the portions of the .T file that we will print out. */
1287 read_tfile __proto((void))
1290 off_t sym_hdr_offset = 0;
1292 /* Determine if this is a .T file (which has no file header), or some
1293 sort of object file (which does have a file header) via the magic
1295 (void) read_seek ((PTR_T) &magic, sizeof (magic), (off_t)0, "Magic number");
1296 if (magic == MIPSELMAGIC || magic == MIPSEBMAGIC)
1298 (void) read_seek ((PTR_T) &global_hdr, sizeof (global_hdr), (off_t)0,
1299 "Global file header");
1301 print_global_hdr (&global_hdr);
1303 if (global_hdr.f_symptr == 0)
1305 printf ("No symbolic header, Goodbye!\n");
1309 sym_hdr_offset = global_hdr.f_symptr;
1312 (void) read_seek ((PTR_T) &sym_hdr,
1317 print_sym_hdr (&sym_hdr);
1319 lines = (LINER *) read_seek ((PTR_T)0,
1321 sym_hdr.cbLineOffset,
1324 dense_nums = (DNR *) read_seek ((PTR_T)0,
1325 sym_hdr.idnMax * sizeof (DNR),
1329 proc_desc = (PDR *) read_seek ((PTR_T)0,
1330 sym_hdr.ipdMax * sizeof (PDR),
1332 "Procedure tables");
1334 l_symbols = (SYMR *) read_seek ((PTR_T)0,
1335 sym_hdr.isymMax * sizeof (SYMR),
1336 sym_hdr.cbSymOffset,
1339 opt_symbols = (OPTR *) read_seek ((PTR_T)0,
1340 sym_hdr.ioptMax * sizeof (OPTR),
1341 sym_hdr.cbOptOffset,
1342 "Optimization symbols");
1344 aux_symbols = (AUXU *) read_seek ((PTR_T)0,
1345 sym_hdr.iauxMax * sizeof (AUXU),
1346 sym_hdr.cbAuxOffset,
1347 "Auxilary symbols");
1349 if (sym_hdr.iauxMax > 0)
1351 aux_used = calloc (sym_hdr.iauxMax, 1);
1352 if (aux_used == (char *)0)
1359 l_strings = (char *) read_seek ((PTR_T)0,
1362 "Local string table");
1364 e_strings = (char *) read_seek ((PTR_T)0,
1366 sym_hdr.cbSsExtOffset,
1367 "External string table");
1369 file_desc = (FDR *) read_seek ((PTR_T)0,
1370 sym_hdr.ifdMax * sizeof (FDR),
1374 rfile_desc = (ulong *) read_seek ((PTR_T)0,
1375 sym_hdr.crfd * sizeof (ulong),
1376 sym_hdr.cbRfdOffset,
1377 "Relative file tables");
1379 e_symbols = (EXTR *) read_seek ((PTR_T)0,
1380 sym_hdr.iextMax * sizeof (EXTR),
1381 sym_hdr.cbExtOffset,
1382 "External symbols");
1397 while ((opt = getopt (argc, argv, "alrs")) != EOF)
1400 default: errors++; break;
1401 case 'a': want_aux++; break; /* print aux table */
1402 case 'l': want_line++; break; /* print line numbers */
1403 case 'r': want_rfd++; break; /* print relative fd's */
1404 case 's': want_scope++; break; /* print scope info */
1407 if (errors || optind != argc - 1)
1409 fprintf (stderr, "Calling Sequence:\n");
1410 fprintf (stderr, "\t%0 [-alrs] <object-or-T-file>\n", argv[0]);
1411 fprintf (stderr, "\n");
1412 fprintf (stderr, "switches:\n");
1413 fprintf (stderr, "\t-a Print out auxiliary table.\n");
1414 fprintf (stderr, "\t-l Print out line numbers.\n");
1415 fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1416 fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1421 * Open and process the input file.
1423 tfile_fd = open (argv[optind], O_RDONLY);
1426 perror (argv[optind]);
1433 * Print any global aux words if any.
1437 long last_aux_in_use;
1439 if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1441 printf ("\nGlobal auxiliary entries before first file:\n");
1442 for (i = 0; i < file_desc[0].iauxBase; i++)
1443 print_aux (aux_symbols[i], 0, aux_used[i]);
1446 if (sym_hdr.ifdMax == 0)
1447 last_aux_in_use = 0;
1450 file_desc[sym_hdr.ifdMax-1].iauxBase +
1451 file_desc[sym_hdr.ifdMax-1].caux - 1;
1453 if (last_aux_in_use < sym_hdr.iauxMax-1)
1455 printf ("\nGlobal auxiliary entries after last file:\n");
1456 for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1457 print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1462 * Print the information for each file.
1464 for (i = 0; i < sym_hdr.ifdMax; i++)
1465 print_file_desc (&file_desc[i], i);
1468 * Print the external symbols.
1470 want_scope = 0; /* scope info is meaning for extern symbols */
1471 printf ("\nThere are %lu external symbols, starting at %lu\n",
1472 (ulong) sym_hdr.iextMax,
1473 (ulong) sym_hdr.cbExtOffset);
1475 for(i = 0; i < sym_hdr.iextMax; i++)
1476 print_symbol (&e_symbols[i].asym, i, e_strings,
1477 aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1481 * Print unused aux symbols now.
1488 for (i = 0; i < sym_hdr.iauxMax; i++)
1494 printf ("\nThe following auxiliary table entries were unused:\n\n");
1498 printf (" #%-5d %11ld 0x%08lx %s\n",
1500 (long) aux_symbols[i].isym,
1501 (long) aux_symbols[i].isym,
1502 type_to_string (aux_symbols, i));
1514 fprintf (stderr, "mips-tdump internal error");
1522 fprintf(stderr, "%s\n", s);
1526 /* Same as `malloc' but report error if no memory available. */
1532 register PTR_T value = malloc (size);
1534 fatal ("Virtual memory exhausted.");