1 /* Read and manage MIPS symbol tables from object modules.
2 Copyright (C) 1991, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <sys/types.h>
37 #include "mips/a.out.h"
38 #endif /* CROSS_COMPILE */
41 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
42 and mips-tdump.c to print them out. This is used on the Alpha,
43 which does not include mips.h.
45 These must match the corresponding definitions in gdb/mipsread.c.
46 Unfortunately, gcc and gdb do not currently share any directories. */
48 #define CODE_MASK 0x8F300
49 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
50 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
51 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
56 typedef const void *CPTR_T
;
60 #if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
65 typedef char *PTR_T
; /* Ultrix 3.1 */
73 #define uchar unsigned char
74 #define ushort unsigned short
75 #define uint unsigned int
76 #define ulong unsigned long
79 /* Do to size_t being defined in sys/types.h and different
80 in stddef.h, we have to do this by hand..... Note, these
81 types are correct for MIPS based systems, and may not be
82 correct for other systems. */
88 /* Redefinition of of storage classes as an enumeration for better
92 #define stStaParam 16 /* Fortran static parameters */
96 #define btVoid 26 /* void basic type */
100 sc_Nil
= scNil
, /* no storage class */
101 sc_Text
= scText
, /* text symbol */
102 sc_Data
= scData
, /* initialized data symbol */
103 sc_Bss
= scBss
, /* un-initialized data symbol */
104 sc_Register
= scRegister
, /* value of symbol is register number */
105 sc_Abs
= scAbs
, /* value of symbol is absolute */
106 sc_Undefined
= scUndefined
, /* who knows? */
107 sc_CdbLocal
= scCdbLocal
, /* variable's value is IN se->va.?? */
108 sc_Bits
= scBits
, /* this is a bit field */
109 sc_CdbSystem
= scCdbSystem
, /* var's value is IN CDB's address space */
110 sc_RegImage
= scRegImage
, /* register value saved on stack */
111 sc_Info
= scInfo
, /* symbol contains debugger information */
112 sc_UserStruct
= scUserStruct
, /* addr in struct user for current process */
113 sc_SData
= scSData
, /* load time only small data */
114 sc_SBss
= scSBss
, /* load time only small common */
115 sc_RData
= scRData
, /* load time only read only data */
116 sc_Var
= scVar
, /* Var parameter (fortran,pascal) */
117 sc_Common
= scCommon
, /* common variable */
118 sc_SCommon
= scSCommon
, /* small common */
119 sc_VarRegister
= scVarRegister
, /* Var parameter in a register */
120 sc_Variant
= scVariant
, /* Variant record */
121 sc_SUndefined
= scSUndefined
, /* small undefined(external) data */
122 sc_Init
= scInit
, /* .init section symbol */
123 sc_Max
= scMax
/* Max storage class+1 */
126 /* Redefinition of symbol type. */
129 st_Nil
= stNil
, /* Nuthin' special */
130 st_Global
= stGlobal
, /* external symbol */
131 st_Static
= stStatic
, /* static */
132 st_Param
= stParam
, /* procedure argument */
133 st_Local
= stLocal
, /* local variable */
134 st_Label
= stLabel
, /* label */
135 st_Proc
= stProc
, /* " " Procedure */
136 st_Block
= stBlock
, /* beginning of block */
137 st_End
= stEnd
, /* end (of anything) */
138 st_Member
= stMember
, /* member (of anything - struct/union/enum */
139 st_Typedef
= stTypedef
, /* type definition */
140 st_File
= stFile
, /* file name */
141 st_RegReloc
= stRegReloc
, /* register relocation */
142 st_Forward
= stForward
, /* forwarding address */
143 st_StaticProc
= stStaticProc
, /* load time only static procs */
144 st_StaParam
= stStaParam
, /* Fortran static parameters */
145 st_Constant
= stConstant
, /* const */
146 st_Str
= stStr
, /* string */
147 st_Number
= stNumber
, /* pure number (ie. 4 NOR 2+2) */
148 st_Expr
= stExpr
, /* 2+2 vs. 4 */
149 st_Type
= stType
, /* post-coercion SER */
150 st_Max
= stMax
/* max type+1 */
153 /* Redefinition of type qualifiers. */
156 tq_Nil
= tqNil
, /* bt is what you see */
157 tq_Ptr
= tqPtr
, /* pointer */
158 tq_Proc
= tqProc
, /* procedure */
159 tq_Array
= tqArray
, /* duh */
160 tq_Far
= tqFar
, /* longer addressing - 8086/8 land */
161 tq_Vol
= tqVol
, /* volatile */
162 tq_Max
= tqMax
/* Max type qualifier+1 */
165 /* Redefinition of basic types. */
168 bt_Nil
= btNil
, /* undefined */
169 bt_Adr
= btAdr
, /* address - integer same size as pointer */
170 bt_Char
= btChar
, /* character */
171 bt_UChar
= btUChar
, /* unsigned character */
172 bt_Short
= btShort
, /* short */
173 bt_UShort
= btUShort
, /* unsigned short */
174 bt_Int
= btInt
, /* int */
175 bt_UInt
= btUInt
, /* unsigned int */
176 bt_Long
= btLong
, /* long */
177 bt_ULong
= btULong
, /* unsigned long */
178 bt_Float
= btFloat
, /* float (real) */
179 bt_Double
= btDouble
, /* Double (real) */
180 bt_Struct
= btStruct
, /* Structure (Record) */
181 bt_Union
= btUnion
, /* Union (variant) */
182 bt_Enum
= btEnum
, /* Enumerated */
183 bt_Typedef
= btTypedef
, /* defined via a typedef, isymRef points */
184 bt_Range
= btRange
, /* subrange of int */
185 bt_Set
= btSet
, /* pascal sets */
186 bt_Complex
= btComplex
, /* fortran complex */
187 bt_DComplex
= btDComplex
, /* fortran double complex */
188 bt_Indirect
= btIndirect
, /* forward or unnamed typedef */
189 bt_FixedDec
= btFixedDec
, /* Fixed Decimal */
190 bt_FloatDec
= btFloatDec
, /* Float Decimal */
191 bt_String
= btString
, /* Varying Length Character String */
192 bt_Bit
= btBit
, /* Aligned Bit String */
193 bt_Picture
= btPicture
, /* Picture */
194 bt_Void
= btVoid
, /* void */
195 bt_Max
= btMax
/* Max basic type+1 */
198 /* Redefinition of the language codes. */
202 lang_Pascal
= langPascal
,
203 lang_Fortran
= langFortran
,
204 lang_Assembler
= langAssembler
,
205 lang_Machine
= langMachine
,
209 lang_Cobol
= langCobol
212 /* Redefinition of the debug level codes. */
214 typedef enum glevel
{
222 /* Keep track of the active scopes. */
223 typedef struct scope
{
224 struct scope
*prev
; /* previous scope */
225 ulong open_sym
; /* symbol opening scope */
226 sc_t sc
; /* storage class */
227 st_t st
; /* symbol type */
230 struct filehdr global_hdr
; /* a.out header */
232 int errors
= 0; /* # of errors */
233 int want_aux
= 0; /* print aux table */
234 int want_line
= 0; /* print line numbers */
235 int want_rfd
= 0; /* print relative file desc's */
236 int want_scope
= 0; /* print scopes for every symbol */
237 int tfile
= 0; /* no global header file */
238 int tfile_fd
; /* file descriptor of .T file */
239 off_t tfile_offset
; /* current offset in .T file */
240 scope_t
*cur_scope
= 0; /* list of active scopes */
241 scope_t
*free_scope
= 0; /* list of freed scopes */
242 HDRR sym_hdr
; /* symbolic header */
243 char *l_strings
; /* local strings */
244 char *e_strings
; /* external strings */
245 SYMR
*l_symbols
; /* local symbols */
246 EXTR
*e_symbols
; /* external symbols */
247 LINER
*lines
; /* line numbers */
248 DNR
*dense_nums
; /* dense numbers */
249 OPTR
*opt_symbols
; /* optimization symbols */
250 AUXU
*aux_symbols
; /* Auxiliary symbols */
251 char *aux_used
; /* map of which aux syms are used */
252 FDR
*file_desc
; /* file tables */
253 ulong
*rfile_desc
; /* relative file tables */
254 PDR
*proc_desc
; /* procedure tables */
256 /* Forward reference for functions. */
257 PTR_T read_seek
__proto((PTR_T
, size_t, off_t
, const char *));
258 void read_tfile
__proto((void));
259 void print_global_hdr
__proto((struct filehdr
*));
260 void print_sym_hdr
__proto((HDRR
*));
261 void print_file_desc
__proto((FDR
*, int));
262 void print_symbol
__proto((SYMR
*, int, char *, AUXU
*, int));
263 void print_aux
__proto((AUXU
, int, int));
264 void emit_aggregate
__proto((char *, AUXU
, AUXU
, const char *));
265 char *st_to_string
__proto((st_t
));
266 char *sc_to_string
__proto((sc_t
));
267 char *glevel_to_string
__proto((glevel_t
));
268 char *lang_to_string
__proto((lang_t
));
269 char *type_to_string
__proto((AUXU
*, int));
272 extern PTR_T malloc
__proto((size_t));
273 extern PTR_T calloc
__proto((size_t, size_t));
274 extern PTR_T realloc
__proto((PTR_T
, size_t));
275 extern void free
__proto((PTR_T
));
282 /* Create a table of debugging stab-codes and corresponding names. */
284 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
285 struct {short code
; char string
[10];} stab_names
[] = {
291 /* Read some bytes at a specified location, and return a pointer. */
294 read_seek (ptr
, size
, offset
, context
)
295 PTR_T ptr
; /* pointer to buffer or NULL */
296 size_t size
; /* # bytes to read */
297 off_t offset
; /* offset to read at */
298 const char *context
; /* context for error message */
302 if (size
== 0) /* nothing to read */
305 if ((ptr
== (PTR_T
)0 && (ptr
= malloc (size
)) == (PTR_T
)0)
306 || (tfile_offset
!= offset
&& lseek (tfile_fd
, offset
, 0) == -1)
307 || (read_size
= read (tfile_fd
, ptr
, size
)) < 0)
313 if (read_size
!= size
)
315 fprintf (stderr
, "%s: read %ld bytes, expected %ld bytes\n",
316 context
, read_size
, (long) size
);
320 tfile_offset
= offset
+ size
;
325 /* Convert language code to string format. */
328 lang_to_string (lang
)
333 case langC
: return "C";
334 case langPascal
: return "Pascal";
335 case langFortran
: return "Fortran";
336 case langAssembler
: return "Assembler";
337 case langMachine
: return "Machine";
338 case langNil
: return "Nil";
339 case langAda
: return "Ada";
340 case langPl1
: return "Pl1";
341 case langCobol
: return "Cobol";
344 return "Unknown language";
348 /* Convert storage class to string. */
351 sc_to_string(storage_class
)
354 switch(storage_class
)
356 case sc_Nil
: return "Nil";
357 case sc_Text
: return "Text";
358 case sc_Data
: return "Data";
359 case sc_Bss
: return "Bss";
360 case sc_Register
: return "Register";
361 case sc_Abs
: return "Abs";
362 case sc_Undefined
: return "Undefined";
363 case sc_CdbLocal
: return "CdbLocal";
364 case sc_Bits
: return "Bits";
365 case sc_CdbSystem
: return "CdbSystem";
366 case sc_RegImage
: return "RegImage";
367 case sc_Info
: return "Info";
368 case sc_UserStruct
: return "UserStruct";
369 case sc_SData
: return "SData";
370 case sc_SBss
: return "SBss";
371 case sc_RData
: return "RData";
372 case sc_Var
: return "Var";
373 case sc_Common
: return "Common";
374 case sc_SCommon
: return "SCommon";
375 case sc_VarRegister
: return "VarRegister";
376 case sc_Variant
: return "Variant";
377 case sc_SUndefined
: return "SUndefined";
378 case sc_Init
: return "Init";
379 case sc_Max
: return "Max";
386 /* Convert symbol type to string. */
389 st_to_string(symbol_type
)
394 case st_Nil
: return "Nil";
395 case st_Global
: return "Global";
396 case st_Static
: return "Static";
397 case st_Param
: return "Param";
398 case st_Local
: return "Local";
399 case st_Label
: return "Label";
400 case st_Proc
: return "Proc";
401 case st_Block
: return "Block";
402 case st_End
: return "End";
403 case st_Member
: return "Member";
404 case st_Typedef
: return "Typedef";
405 case st_File
: return "File";
406 case st_RegReloc
: return "RegReloc";
407 case st_Forward
: return "Forward";
408 case st_StaticProc
: return "StaticProc";
409 case st_Constant
: return "Constant";
410 case st_StaParam
: return "StaticParam";
411 case st_Str
: return "String";
412 case st_Number
: return "Number";
413 case st_Expr
: return "Expr";
414 case st_Type
: return "Type";
415 case st_Max
: return "Max";
422 /* Convert debug level to string. */
425 glevel_to_string (g_level
)
430 case GLEVEL_0
: return "G0";
431 case GLEVEL_1
: return "G1";
432 case GLEVEL_2
: return "G2";
433 case GLEVEL_3
: return "G3";
440 /* Convert the type information to string format. */
443 type_to_string (aux_ptr
, index
)
457 static char buffer1
[1024];
458 static char buffer2
[1024];
461 char *used_ptr
= aux_used
+ (aux_ptr
- aux_symbols
);
463 for (i
= 0; i
< 7; i
++)
465 qualifiers
[i
].low_bound
= 0;
466 qualifiers
[i
].high_bound
= 0;
467 qualifiers
[i
].stride
= 0;
471 u
= aux_ptr
[index
++];
473 return "-1 (no type)";
475 basic_type
= (bt_t
) u
.ti
.bt
;
476 qualifiers
[0].type
= (tq_t
) u
.ti
.tq0
;
477 qualifiers
[1].type
= (tq_t
) u
.ti
.tq1
;
478 qualifiers
[2].type
= (tq_t
) u
.ti
.tq2
;
479 qualifiers
[3].type
= (tq_t
) u
.ti
.tq3
;
480 qualifiers
[4].type
= (tq_t
) u
.ti
.tq4
;
481 qualifiers
[5].type
= (tq_t
) u
.ti
.tq5
;
482 qualifiers
[6].type
= tq_Nil
;
485 * Go get the basic type.
489 case bt_Nil
: /* undefined */
493 case bt_Adr
: /* address - integer same size as pointer */
494 strcpy (p1
, "address");
497 case bt_Char
: /* character */
501 case bt_UChar
: /* unsigned character */
502 strcpy (p1
, "unsigned char");
505 case bt_Short
: /* short */
506 strcpy (p1
, "short");
509 case bt_UShort
: /* unsigned short */
510 strcpy (p1
, "unsigned short");
513 case bt_Int
: /* int */
517 case bt_UInt
: /* unsigned int */
518 strcpy (p1
, "unsigned int");
521 case bt_Long
: /* long */
525 case bt_ULong
: /* unsigned long */
526 strcpy (p1
, "unsigned long");
529 case bt_Float
: /* float (real) */
530 strcpy (p1
, "float");
533 case bt_Double
: /* Double (real) */
534 strcpy (p1
, "double");
537 /* Structures add 1-2 aux words:
538 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
539 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
541 case bt_Struct
: /* Structure (Record) */
542 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "struct");
544 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
545 used_ptr
[++index
] = 1;
547 index
++; /* skip aux words */
550 /* Unions add 1-2 aux words:
551 1st word is [ST_RFDESCAPE, offset] pointer to union def;
552 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
554 case bt_Union
: /* Union */
555 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "union");
557 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
558 used_ptr
[++index
] = 1;
560 index
++; /* skip aux words */
563 /* Enumerations add 1-2 aux words:
564 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
565 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
567 case bt_Enum
: /* Enumeration */
568 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "enum");
570 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
571 used_ptr
[++index
] = 1;
573 index
++; /* skip aux words */
576 case bt_Typedef
: /* defined via a typedef, isymRef points */
577 strcpy (p1
, "typedef");
580 case bt_Range
: /* subrange of int */
581 strcpy (p1
, "subrange");
584 case bt_Set
: /* pascal sets */
588 case bt_Complex
: /* fortran complex */
589 strcpy (p1
, "complex");
592 case bt_DComplex
: /* fortran double complex */
593 strcpy (p1
, "double complex");
596 case bt_Indirect
: /* forward or unnamed typedef */
597 strcpy (p1
, "forward/unamed typedef");
600 case bt_FixedDec
: /* Fixed Decimal */
601 strcpy (p1
, "fixed decimal");
604 case bt_FloatDec
: /* Float Decimal */
605 strcpy (p1
, "float decimal");
608 case bt_String
: /* Varying Length Character String */
609 strcpy (p1
, "string");
612 case bt_Bit
: /* Aligned Bit String */
616 case bt_Picture
: /* Picture */
617 strcpy (p1
, "picture");
620 case bt_Void
: /* Void */
625 sprintf (p1
, "Unknown basic type %d", (int) basic_type
);
629 p1
+= strlen (buffer1
);
632 * If this is a bitfield, get the bitsize.
639 bitsize
= aux_ptr
[index
++].width
;
640 sprintf (p1
, " : %d", bitsize
);
641 p1
+= strlen (buffer1
);
646 * Deal with any qualifiers.
648 if (qualifiers
[0].type
!= tq_Nil
)
651 * Snarf up any array bounds in the correct order. Arrays
652 * store 5 successive words in the aux. table:
653 * word 0 RNDXR to type of the bounds (ie, int)
654 * word 1 Current file descriptor index
656 * word 3 high bound (or -1 if [])
657 * word 4 stride size in bits
659 for (i
= 0; i
< 7; i
++)
661 if (qualifiers
[i
].type
== tq_Array
)
663 qualifiers
[i
].low_bound
= aux_ptr
[index
+2].dnLow
;
664 qualifiers
[i
].high_bound
= aux_ptr
[index
+3].dnHigh
;
665 qualifiers
[i
].stride
= aux_ptr
[index
+4].width
;
667 used_ptr
[index
+1] = 1;
668 used_ptr
[index
+2] = 1;
669 used_ptr
[index
+3] = 1;
670 used_ptr
[index
+4] = 1;
676 * Now print out the qualifiers.
678 for (i
= 0; i
< 6; i
++)
680 switch (qualifiers
[i
].type
)
687 strcpy (p2
, "ptr to ");
688 p2
+= sizeof ("ptr to ")-1;
692 strcpy (p2
, "volatile ");
693 p2
+= sizeof ("volatile ")-1;
698 p2
+= sizeof ("far ")-1;
702 strcpy (p2
, "func. ret. ");
703 p2
+= sizeof ("func. ret. ");
711 /* Print array bounds reversed (ie, in the order the C
712 programmer writes them). C is such a fun language.... */
714 while (i
< 5 && qualifiers
[i
+1].type
== tq_Array
)
717 for (j
= i
; j
>= first_array
; j
--)
719 strcpy (p2
, "array [");
720 p2
+= sizeof ("array [")-1;
721 if (qualifiers
[j
].low_bound
!= 0)
723 "%ld:%ld {%ld bits}",
724 (long) qualifiers
[j
].low_bound
,
725 (long) qualifiers
[j
].high_bound
,
726 (long) qualifiers
[j
].stride
);
728 else if (qualifiers
[j
].high_bound
!= -1)
731 (long) (qualifiers
[j
].high_bound
+ 1),
732 (long) (qualifiers
[j
].stride
));
735 sprintf (p2
, " {%ld bits}", (long) (qualifiers
[j
].stride
));
738 strcpy (p2
, "] of ");
739 p2
+= sizeof ("] of ")-1;
747 strcpy (p2
, buffer1
);
752 /* Print out the global file header for object files. */
755 print_global_hdr (ptr
)
758 char *time
= ctime ((time_t *)&ptr
->f_timdat
);
759 ushort flags
= ptr
->f_flags
;
761 printf("Global file header:\n");
762 printf(" %-*s 0x%x\n", 24, "magic number", (ushort
) ptr
->f_magic
);
763 printf(" %-*s %d\n", 24, "# sections", (int) ptr
->f_nscns
);
764 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr
->f_timdat
, time
);
765 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr
->f_symptr
);
766 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr
->f_nsyms
);
767 printf(" %-*s %ld\n", 24, "optional header", (long) ptr
->f_opthdr
);
768 printf(" %-*s 0x%x", 24, "flags", (ushort
) flags
);
770 if ((flags
& F_RELFLG
) != 0)
771 printf (", F_RELFLG");
773 if ((flags
& F_EXEC
) != 0)
776 if ((flags
& F_LNNO
) != 0)
779 if ((flags
& F_LSYMS
) != 0)
780 printf (", F_LSYMS");
782 if ((flags
& F_MINMAL
) != 0)
783 printf (", F_MINMAL");
785 if ((flags
& F_UPDATE
) != 0)
786 printf (", F_UPDATE");
788 if ((flags
& F_SWABD
) != 0)
789 printf (", F_SWABD");
791 if ((flags
& F_AR16WR
) != 0)
792 printf (", F_AR16WR");
794 if ((flags
& F_AR32WR
) != 0)
795 printf (", F_AR32WR");
797 if ((flags
& F_AR32W
) != 0)
798 printf (", F_AR32W");
800 if ((flags
& F_PATCH
) != 0)
801 printf (", F_PATCH/F_NODF");
807 /* Print out the symbolic header. */
810 print_sym_hdr (sym_ptr
)
815 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
816 sym_ptr
->magic
& 0xffff,
817 (sym_ptr
->vstamp
& 0xffff) >> 8,
818 sym_ptr
->vstamp
& 0xff);
820 printf(" %-*s %11s %11s %11s\n", width
, "Info", "Offset", "Number", "Bytes");
821 printf(" %-*s %11s %11s %11s\n", width
, "====", "======", "======", "=====\n");
823 printf(" %-*s %11ld %11ld %11ld [%d]\n", width
, "Line numbers",
824 (long)sym_ptr
->cbLineOffset
,
825 (long)sym_ptr
->cbLine
,
826 (long)sym_ptr
->cbLine
,
827 (int)sym_ptr
->ilineMax
);
829 printf(" %-*s %11ld %11ld %11ld\n", width
, "Dense numbers",
830 (long)sym_ptr
->cbDnOffset
,
831 (long)sym_ptr
->idnMax
,
832 (long)(sym_ptr
->idnMax
* sizeof (DNR
)));
834 printf(" %-*s %11ld %11ld %11ld\n", width
, "Procedures Tables",
835 (long)sym_ptr
->cbPdOffset
,
836 (long)sym_ptr
->ipdMax
,
837 (long)(sym_ptr
->ipdMax
* sizeof (PDR
)));
839 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Symbols",
840 (long)sym_ptr
->cbSymOffset
,
841 (long)sym_ptr
->isymMax
,
842 (long)(sym_ptr
->isymMax
* sizeof (SYMR
)));
844 printf(" %-*s %11ld %11ld %11ld\n", width
, "Optimization Symbols",
845 (long)sym_ptr
->cbOptOffset
,
846 (long)sym_ptr
->ioptMax
,
847 (long)(sym_ptr
->ioptMax
* sizeof (OPTR
)));
849 printf(" %-*s %11ld %11ld %11ld\n", width
, "Auxiliary Symbols",
850 (long)sym_ptr
->cbAuxOffset
,
851 (long)sym_ptr
->iauxMax
,
852 (long)(sym_ptr
->iauxMax
* sizeof (AUXU
)));
854 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Strings",
855 (long)sym_ptr
->cbSsOffset
,
856 (long)sym_ptr
->issMax
,
857 (long)sym_ptr
->issMax
);
859 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Strings",
860 (long)sym_ptr
->cbSsExtOffset
,
861 (long)sym_ptr
->issExtMax
,
862 (long)sym_ptr
->issExtMax
);
864 printf(" %-*s %11ld %11ld %11ld\n", width
, "File Tables",
865 (long)sym_ptr
->cbFdOffset
,
866 (long)sym_ptr
->ifdMax
,
867 (long)(sym_ptr
->ifdMax
* sizeof (FDR
)));
869 printf(" %-*s %11ld %11ld %11ld\n", width
, "Relative Files",
870 (long)sym_ptr
->cbRfdOffset
,
872 (long)(sym_ptr
->crfd
* sizeof (ulong
)));
874 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Symbols",
875 (long)sym_ptr
->cbExtOffset
,
876 (long)sym_ptr
->iextMax
,
877 (long)(sym_ptr
->iextMax
* sizeof (EXTR
)));
881 /* Print out a symbol. */
884 print_symbol (sym_ptr
, number
, strbase
, aux_base
, ifd
)
891 sc_t storage_class
= (sc_t
) sym_ptr
->sc
;
892 st_t symbol_type
= (st_t
) sym_ptr
->st
;
893 ulong index
= sym_ptr
->index
;
894 char *used_ptr
= aux_used
+ (aux_base
- aux_symbols
);
897 printf ("\n Symbol# %d: \"%s\"\n", number
, sym_ptr
->iss
+ strbase
);
899 if (aux_base
!= (AUXU
*)0 && index
!= indexNil
)
908 printf (" End+1 symbol: %ld\n", index
);
911 if (free_scope
== (scope_t
*)0)
912 scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
915 scope_ptr
= free_scope
;
916 free_scope
= scope_ptr
->prev
;
918 scope_ptr
->open_sym
= number
;
919 scope_ptr
->st
= symbol_type
;
920 scope_ptr
->sc
= storage_class
;
921 scope_ptr
->prev
= cur_scope
;
922 cur_scope
= scope_ptr
;
927 if (storage_class
== sc_Text
|| storage_class
== sc_Info
)
928 printf (" First symbol: %ld\n", index
);
932 printf (" First symbol: %ld\n", aux_base
[index
].isym
);
937 if (cur_scope
== (scope_t
*)0)
938 printf (" Can't pop end scope\n");
941 scope_ptr
= cur_scope
;
942 cur_scope
= scope_ptr
->prev
;
943 scope_ptr
->prev
= free_scope
;
944 free_scope
= scope_ptr
;
951 if (MIPS_IS_STAB(sym_ptr
))
953 else if (ifd
== -1) /* local symbol */
955 used_ptr
[index
] = used_ptr
[index
+1] = 1;
956 printf (" End+1 symbol: %-7ld Type: %s\n",
957 aux_base
[index
].isym
, type_to_string (aux_base
, index
+1));
959 else /* global symbol */
960 printf (" Local symbol: %ld\n", index
);
964 if (free_scope
== (scope_t
*)0)
965 scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
968 scope_ptr
= free_scope
;
969 free_scope
= scope_ptr
->prev
;
971 scope_ptr
->open_sym
= number
;
972 scope_ptr
->st
= symbol_type
;
973 scope_ptr
->sc
= storage_class
;
974 scope_ptr
->prev
= cur_scope
;
975 cur_scope
= scope_ptr
;
980 if (!MIPS_IS_STAB (sym_ptr
))
983 printf (" Type: %s\n",
984 type_to_string (aux_base
, index
));
991 printf (" Scopes: ");
992 if (cur_scope
== (scope_t
*)0)
996 for (scope_ptr
= cur_scope
;
997 scope_ptr
!= (scope_t
*)0;
998 scope_ptr
= scope_ptr
->prev
)
1001 if (scope_ptr
->st
== st_Proc
|| scope_ptr
->st
== st_StaticProc
)
1003 else if (scope_ptr
->st
== st_File
)
1005 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Text
)
1007 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Info
)
1012 printf (" %ld [%s]", scope_ptr
->open_sym
, class);
1018 printf (" Value: %-13ld ",
1019 (long)sym_ptr
->value
);
1021 printf ("String index: %ld\n", (long)sym_ptr
->iss
);
1023 printf ("String index: %-11ld Ifd: %d\n",
1024 (long)sym_ptr
->iss
, ifd
);
1026 printf (" Symbol type: %-11sStorage class: %-11s",
1027 st_to_string (symbol_type
), sc_to_string (storage_class
));
1029 if (MIPS_IS_STAB(sym_ptr
))
1031 register int i
= sizeof(stab_names
) / sizeof(stab_names
[0]);
1032 char *stab_name
= "stab";
1033 short code
= MIPS_UNMARK_STAB(sym_ptr
->index
);
1035 if (stab_names
[i
].code
== code
)
1037 stab_name
= stab_names
[i
].string
;
1040 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr
->index
, stab_name
);
1042 else if (sym_ptr
->st
== stLabel
&& sym_ptr
->index
!= indexNil
)
1043 printf ("Index: %ld (line#)\n", (long)sym_ptr
->index
);
1045 printf ("Index: %ld\n", (long)sym_ptr
->index
);
1050 /* Print out a word from the aux. table in various formats. */
1053 print_aux (u
, auxi
, used
)
1058 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1059 (used
) ? " " : "* ",
1063 (long) u
.rndx
.index
,
1076 /* Write aggregate information to a string. */
1079 emit_aggregate (string
, u
, u2
, which
)
1085 int ifd
= u
.rndx
.rfd
;
1086 int index
= u
.rndx
.index
;
1087 int sym_base
, ss_base
;
1090 if (ifd
== ST_RFDESCAPE
)
1093 sym_base
= file_desc
[ifd
].isymBase
;
1094 ss_base
= file_desc
[ifd
].issBase
;
1096 name
= (index
== indexNil
) ? 0 : l_symbols
[index
+ sym_base
].iss
;
1098 "%s %s { ifd = %d, index = %d }",
1100 (name
== 0) ? "/* no name */" : &l_strings
[ ss_base
+ name
],
1106 /* Print out information about a file descriptor, and the symbols,
1107 procedures, and line numbers within it. */
1110 print_file_desc (fdp
, number
)
1120 str_base
= l_strings
+ fdp
->issBase
;
1121 aux_base
= aux_symbols
+ fdp
->iauxBase
;
1122 used_base
= aux_used
+ (aux_base
- aux_symbols
);
1124 printf ("\nFile #%d, \"%s\"\n\n", number
, str_base
+ fdp
->rss
);
1126 printf (" Name index = %-10ld Readin = %s\n",
1127 (long) fdp
->rss
, (fdp
->fReadin
) ? "Yes" : "No");
1129 printf (" Merge = %-10s Endian = %s\n",
1130 (fdp
->fMerge
) ? "Yes" : "No",
1131 (fdp
->fBigendian
) ? "BIG" : "LITTLE");
1133 printf (" Debug level = %-10s Language = %s\n",
1134 glevel_to_string (fdp
->glevel
),
1135 lang_to_string((lang_t
) fdp
->lang
));
1137 printf (" Adr = 0x%08lx\n\n", (long) fdp
->adr
);
1139 printf(" %-*s %11s %11s %11s %11s\n", width
, "Info", "Start", "Number", "Size", "Offset");
1140 printf(" %-*s %11s %11s %11s %11s\n", width
, "====", "=====", "======", "====", "======");
1142 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1143 width
, "Local strings",
1144 (ulong
) fdp
->issBase
,
1147 (ulong
) (fdp
->issBase
+ sym_hdr
.cbSsOffset
));
1149 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1150 width
, "Local symbols",
1151 (ulong
) fdp
->isymBase
,
1153 (ulong
) (fdp
->csym
* sizeof (SYMR
)),
1154 (ulong
) (fdp
->isymBase
* sizeof (SYMR
) + sym_hdr
.cbSymOffset
));
1156 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1157 width
, "Line numbers",
1158 (ulong
) fdp
->cbLineOffset
,
1160 (ulong
) fdp
->cbLine
,
1161 (ulong
) (fdp
->cbLineOffset
+ sym_hdr
.cbLineOffset
));
1163 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1164 width
, "Optimization symbols",
1165 (ulong
) fdp
->ioptBase
,
1167 (ulong
) (fdp
->copt
* sizeof (OPTR
)),
1168 (ulong
) (fdp
->ioptBase
* sizeof (OPTR
) + sym_hdr
.cbOptOffset
));
1170 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1171 width
, "Procedures",
1172 (ulong
) fdp
->ipdFirst
,
1174 (ulong
) (fdp
->cpd
* sizeof (PDR
)),
1175 (ulong
) (fdp
->ipdFirst
* sizeof (PDR
) + sym_hdr
.cbPdOffset
));
1177 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1178 width
, "Auxiliary symbols",
1179 (ulong
) fdp
->iauxBase
,
1181 (ulong
) (fdp
->caux
* sizeof (AUXU
)),
1182 (ulong
) (fdp
->iauxBase
* sizeof(AUXU
) + sym_hdr
.cbAuxOffset
));
1184 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1185 width
, "Relative Files",
1186 (ulong
) fdp
->rfdBase
,
1188 (ulong
) (fdp
->crfd
* sizeof (ulong
)),
1189 (ulong
) (fdp
->rfdBase
* sizeof(ulong
) + sym_hdr
.cbRfdOffset
));
1192 if (want_scope
&& cur_scope
!= (scope_t
*)0)
1193 printf ("\n Warning scope does not start at 0!\n");
1196 * print the info about the symbol table.
1198 printf ("\n There are %lu local symbols, starting at %lu\n",
1200 (ulong
) (fdp
->isymBase
+ sym_hdr
.cbSymOffset
));
1202 for(symi
= fdp
->isymBase
; symi
< (fdp
->csym
+ fdp
->isymBase
); symi
++)
1203 print_symbol (&l_symbols
[symi
],
1204 symi
- fdp
->isymBase
,
1209 if (want_scope
&& cur_scope
!= (scope_t
*)0)
1210 printf ("\n Warning scope does not end at 0!\n");
1213 * print the aux. table if desired.
1216 if (want_aux
&& fdp
->caux
!= 0)
1220 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1222 (ulong
) (fdp
->iauxBase
+ sym_hdr
.cbAuxOffset
));
1224 for (auxi
= fdp
->iauxBase
; auxi
< (fdp
->caux
+ fdp
->iauxBase
); auxi
++)
1225 print_aux (aux_base
[auxi
], auxi
, used_base
[auxi
]);
1229 * print the relative file descriptors.
1231 if (want_rfd
&& fdp
->crfd
!= 0)
1235 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1237 (ulong
) fdp
->rfdBase
);
1239 rfd_ptr
= rfile_desc
+ fdp
->rfdBase
;
1240 for (i
= 0; i
< fdp
->crfd
; i
++)
1242 printf ("\t#%-5ld %11ld, 0x%08lx\n", i
, *rfd_ptr
, *rfd_ptr
);
1248 * do the procedure descriptors.
1250 printf ("\n There are %lu procedure descriptor entries, ", (ulong
) fdp
->cpd
);
1251 printf ("starting at %lu.\n", (ulong
) fdp
->ipdFirst
);
1253 for (pdi
= fdp
->ipdFirst
; pdi
< (fdp
->cpd
+ fdp
->ipdFirst
); pdi
++)
1255 PDR
*proc_ptr
= &proc_desc
[pdi
];
1256 printf ("\n\tProcedure descriptor %d:\n", (pdi
- fdp
->ipdFirst
));
1258 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1259 (long) l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
,
1260 l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
+ str_base
);
1262 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1263 (long) proc_ptr
->regmask
,
1264 (long) proc_ptr
->regoffset
,
1265 (long) proc_ptr
->fregmask
,
1266 (long) proc_ptr
->fregoffset
);
1268 printf ("\t .frame $%d,%ld,$%d\n",
1269 (int) proc_ptr
->framereg
,
1270 (long) proc_ptr
->frameoffset
,
1271 (int) proc_ptr
->pcreg
);
1273 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1274 (long) proc_ptr
->iopt
,
1275 (long) proc_ptr
->isym
);
1277 printf ("\t First line # = %-11ld Last line # = %ld\n",
1278 (long) proc_ptr
->lnLow
,
1279 (long) proc_ptr
->lnHigh
);
1281 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1282 (long) proc_ptr
->cbLineOffset
,
1283 (long) proc_ptr
->adr
);
1286 * print the line number entries.
1289 if (want_line
&& fdp
->cline
!= 0)
1292 long cur_line
= proc_ptr
->lnLow
;
1293 uchar
*line_ptr
= (((uchar
*)lines
) + proc_ptr
->cbLineOffset
1294 + fdp
->cbLineOffset
);
1297 if (pdi
== fdp
->cpd
+ fdp
->ipdFirst
- 1) /* last procedure */
1298 line_end
= ((uchar
*)lines
) + fdp
->cbLine
+ fdp
->cbLineOffset
;
1299 else /* not last proc. */
1300 line_end
= (((uchar
*)lines
) + proc_desc
[pdi
+1].cbLineOffset
1301 + fdp
->cbLineOffset
);
1303 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1304 (ulong
) (line_end
- line_ptr
),
1305 (ulong
) (fdp
->ilineBase
+ sym_hdr
.cbLineOffset
));
1307 while (line_ptr
< line_end
)
1308 { /* sign extend nibble */
1309 delta
= ((*line_ptr
>> 4) ^ 0x8) - 0x8;
1310 count
= (*line_ptr
& 0xf) + 1;
1315 delta
= (((line_ptr
[1]) & 0xff) << 8) + ((line_ptr
[2]) & 0xff);
1316 delta
= (delta
^ 0x8000) - 0x8000;
1321 printf ("\t Line %11ld, delta %5d, count %2d\n",
1331 /* Read in the portions of the .T file that we will print out. */
1334 read_tfile
__proto((void))
1337 off_t sym_hdr_offset
= 0;
1339 (void) read_seek ((PTR_T
) &magic
, sizeof (magic
), (off_t
)0, "Magic number");
1342 /* Print out the global header, since this is not a T-file. */
1344 (void) read_seek ((PTR_T
) &global_hdr
, sizeof (global_hdr
), (off_t
)0,
1345 "Global file header");
1347 print_global_hdr (&global_hdr
);
1349 if (global_hdr
.f_symptr
== 0)
1351 printf ("No symbolic header, Goodbye!\n");
1355 sym_hdr_offset
= global_hdr
.f_symptr
;
1358 (void) read_seek ((PTR_T
) &sym_hdr
,
1363 print_sym_hdr (&sym_hdr
);
1365 lines
= (LINER
*) read_seek ((PTR_T
)0,
1367 sym_hdr
.cbLineOffset
,
1370 dense_nums
= (DNR
*) read_seek ((PTR_T
)0,
1371 sym_hdr
.idnMax
* sizeof (DNR
),
1375 proc_desc
= (PDR
*) read_seek ((PTR_T
)0,
1376 sym_hdr
.ipdMax
* sizeof (PDR
),
1378 "Procedure tables");
1380 l_symbols
= (SYMR
*) read_seek ((PTR_T
)0,
1381 sym_hdr
.isymMax
* sizeof (SYMR
),
1382 sym_hdr
.cbSymOffset
,
1385 opt_symbols
= (OPTR
*) read_seek ((PTR_T
)0,
1386 sym_hdr
.ioptMax
* sizeof (OPTR
),
1387 sym_hdr
.cbOptOffset
,
1388 "Optimization symbols");
1390 aux_symbols
= (AUXU
*) read_seek ((PTR_T
)0,
1391 sym_hdr
.iauxMax
* sizeof (AUXU
),
1392 sym_hdr
.cbAuxOffset
,
1393 "Auxiliary symbols");
1395 if (sym_hdr
.iauxMax
> 0)
1397 aux_used
= calloc (sym_hdr
.iauxMax
, 1);
1398 if (aux_used
== (char *)0)
1405 l_strings
= (char *) read_seek ((PTR_T
)0,
1408 "Local string table");
1410 e_strings
= (char *) read_seek ((PTR_T
)0,
1412 sym_hdr
.cbSsExtOffset
,
1413 "External string table");
1415 file_desc
= (FDR
*) read_seek ((PTR_T
)0,
1416 sym_hdr
.ifdMax
* sizeof (FDR
),
1420 rfile_desc
= (ulong
*) read_seek ((PTR_T
)0,
1421 sym_hdr
.crfd
* sizeof (ulong
),
1422 sym_hdr
.cbRfdOffset
,
1423 "Relative file tables");
1425 e_symbols
= (EXTR
*) read_seek ((PTR_T
)0,
1426 sym_hdr
.iextMax
* sizeof (EXTR
),
1427 sym_hdr
.cbExtOffset
,
1428 "External symbols");
1443 while ((opt
= getopt (argc
, argv
, "alrst")) != EOF
)
1446 default: errors
++; break;
1447 case 'a': want_aux
++; break; /* print aux table */
1448 case 'l': want_line
++; break; /* print line numbers */
1449 case 'r': want_rfd
++; break; /* print relative fd's */
1450 case 's': want_scope
++; break; /* print scope info */
1451 case 't': tfile
++; break; /* this is a tfile (without header), and not a .o */
1454 if (errors
|| optind
!= argc
- 1)
1456 fprintf (stderr
, "Calling Sequence:\n");
1457 fprintf (stderr
, "\t%s [-alrst] <object-or-T-file>\n", argv
[0]);
1458 fprintf (stderr
, "\n");
1459 fprintf (stderr
, "switches:\n");
1460 fprintf (stderr
, "\t-a Print out auxiliary table.\n");
1461 fprintf (stderr
, "\t-l Print out line numbers.\n");
1462 fprintf (stderr
, "\t-r Print out relative file descriptors.\n");
1463 fprintf (stderr
, "\t-s Print out the current scopes for an item.\n");
1464 fprintf (stderr
, "\t-t Assume there is no global header (ie, a T-file).\n");
1469 * Open and process the input file.
1471 tfile_fd
= open (argv
[optind
], O_RDONLY
);
1474 perror (argv
[optind
]);
1481 * Print any global aux words if any.
1485 long last_aux_in_use
;
1487 if (sym_hdr
.ifdMax
!= 0 && file_desc
[0].iauxBase
!= 0)
1489 printf ("\nGlobal auxiliary entries before first file:\n");
1490 for (i
= 0; i
< file_desc
[0].iauxBase
; i
++)
1491 print_aux (aux_symbols
[i
], 0, aux_used
[i
]);
1494 if (sym_hdr
.ifdMax
== 0)
1495 last_aux_in_use
= 0;
1498 file_desc
[sym_hdr
.ifdMax
-1].iauxBase
+
1499 file_desc
[sym_hdr
.ifdMax
-1].caux
- 1;
1501 if (last_aux_in_use
< sym_hdr
.iauxMax
-1)
1503 printf ("\nGlobal auxiliary entries after last file:\n");
1504 for (i
= last_aux_in_use
; i
< sym_hdr
.iauxMax
; i
++)
1505 print_aux (aux_symbols
[i
], i
- last_aux_in_use
, aux_used
[i
]);
1510 * Print the information for each file.
1512 for (i
= 0; i
< sym_hdr
.ifdMax
; i
++)
1513 print_file_desc (&file_desc
[i
], i
);
1516 * Print the external symbols.
1518 want_scope
= 0; /* scope info is meaning for extern symbols */
1519 printf ("\nThere are %lu external symbols, starting at %lu\n",
1520 (ulong
) sym_hdr
.iextMax
,
1521 (ulong
) sym_hdr
.cbExtOffset
);
1523 for(i
= 0; i
< sym_hdr
.iextMax
; i
++)
1524 print_symbol (&e_symbols
[i
].asym
, i
, e_strings
,
1525 aux_symbols
+ file_desc
[e_symbols
[i
].ifd
].iauxBase
,
1529 * Print unused aux symbols now.
1536 for (i
= 0; i
< sym_hdr
.iauxMax
; i
++)
1542 printf ("\nThe following auxiliary table entries were unused:\n\n");
1546 printf (" #%-5d %11ld 0x%08lx %s\n",
1548 (long) aux_symbols
[i
].isym
,
1549 (long) aux_symbols
[i
].isym
,
1550 type_to_string (aux_symbols
, i
));
1562 fprintf (stderr
, "mips-tdump internal error");
1570 fprintf(stderr
, "%s\n", s
);
1574 /* Same as `malloc' but report error if no memory available. */
1580 register PTR_T value
= malloc (size
);
1582 fatal ("Virtual memory exhausted.");