1 /* Read and manage MIPS symbol tables from object modules.
2 Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999
3 Free Software Foundation, Inc.
4 Contributed by hartzell@boulder.colorado.edu,
5 Rewritten by meissner@osf.org.
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
33 #include "mips/a.out.h"
34 #endif /* CROSS_COMPILE */
37 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
38 and mips-tdump.c to print them out. This is used on the Alpha,
39 which does not include mips.h.
41 These must match the corresponding definitions in gdb/mipsread.c.
42 Unfortunately, gcc and gdb do not currently share any directories. */
44 #define CODE_MASK 0x8F300
45 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
46 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
47 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
50 #define __proto(x) PARAMS(x)
52 typedef const PTR_T CPTR_T
;
54 #define uchar unsigned char
55 #define ushort unsigned short
56 #define uint unsigned int
57 #define ulong unsigned long
59 void fatal
PROTO ((const char *)) ATTRIBUTE_NORETURN
;
60 void fancy_abort
PROTO ((void)) ATTRIBUTE_NORETURN
;
66 fprintf(stderr
, "%s\n", s
);
67 exit(FATAL_EXIT_CODE
);
70 /* Due to size_t being defined in sys/types.h and different
71 in stddef.h, we have to do this by hand..... Note, these
72 types are correct for MIPS based systems, and may not be
73 correct for other systems. */
79 /* Redefinition of storage classes as an enumeration for better
83 #define stStaParam 16 /* Fortran static parameters */
87 #define btVoid 26 /* void basic type */
91 sc_Nil
= scNil
, /* no storage class */
92 sc_Text
= scText
, /* text symbol */
93 sc_Data
= scData
, /* initialized data symbol */
94 sc_Bss
= scBss
, /* un-initialized data symbol */
95 sc_Register
= scRegister
, /* value of symbol is register number */
96 sc_Abs
= scAbs
, /* value of symbol is absolute */
97 sc_Undefined
= scUndefined
, /* who knows? */
98 sc_CdbLocal
= scCdbLocal
, /* variable's value is IN se->va.?? */
99 sc_Bits
= scBits
, /* this is a bit field */
100 sc_CdbSystem
= scCdbSystem
, /* var's value is IN CDB's address space */
101 sc_RegImage
= scRegImage
, /* register value saved on stack */
102 sc_Info
= scInfo
, /* symbol contains debugger information */
103 sc_UserStruct
= scUserStruct
, /* addr in struct user for current process */
104 sc_SData
= scSData
, /* load time only small data */
105 sc_SBss
= scSBss
, /* load time only small common */
106 sc_RData
= scRData
, /* load time only read only data */
107 sc_Var
= scVar
, /* Var parameter (fortran,pascal) */
108 sc_Common
= scCommon
, /* common variable */
109 sc_SCommon
= scSCommon
, /* small common */
110 sc_VarRegister
= scVarRegister
, /* Var parameter in a register */
111 sc_Variant
= scVariant
, /* Variant record */
112 sc_SUndefined
= scSUndefined
, /* small undefined(external) data */
113 sc_Init
= scInit
, /* .init section symbol */
114 sc_Max
= scMax
/* Max storage class+1 */
117 /* Redefinition of symbol type. */
120 st_Nil
= stNil
, /* Nuthin' special */
121 st_Global
= stGlobal
, /* external symbol */
122 st_Static
= stStatic
, /* static */
123 st_Param
= stParam
, /* procedure argument */
124 st_Local
= stLocal
, /* local variable */
125 st_Label
= stLabel
, /* label */
126 st_Proc
= stProc
, /* " " Procedure */
127 st_Block
= stBlock
, /* beginning of block */
128 st_End
= stEnd
, /* end (of anything) */
129 st_Member
= stMember
, /* member (of anything - struct/union/enum */
130 st_Typedef
= stTypedef
, /* type definition */
131 st_File
= stFile
, /* file name */
132 st_RegReloc
= stRegReloc
, /* register relocation */
133 st_Forward
= stForward
, /* forwarding address */
134 st_StaticProc
= stStaticProc
, /* load time only static procs */
135 st_StaParam
= stStaParam
, /* Fortran static parameters */
136 st_Constant
= stConstant
, /* const */
138 st_Struct
= stStruct
, /* struct */
139 st_Union
= stUnion
, /* union */
140 st_Enum
= stEnum
, /* enum */
142 st_Str
= stStr
, /* string */
143 st_Number
= stNumber
, /* pure number (ie. 4 NOR 2+2) */
144 st_Expr
= stExpr
, /* 2+2 vs. 4 */
145 st_Type
= stType
, /* post-coercion SER */
146 st_Max
= stMax
/* max type+1 */
149 /* Redefinition of type qualifiers. */
152 tq_Nil
= tqNil
, /* bt is what you see */
153 tq_Ptr
= tqPtr
, /* pointer */
154 tq_Proc
= tqProc
, /* procedure */
155 tq_Array
= tqArray
, /* duh */
156 tq_Far
= tqFar
, /* longer addressing - 8086/8 land */
157 tq_Vol
= tqVol
, /* volatile */
158 tq_Max
= tqMax
/* Max type qualifier+1 */
161 /* Redefinition of basic types. */
164 bt_Nil
= btNil
, /* undefined */
165 bt_Adr
= btAdr
, /* address - integer same size as pointer */
166 bt_Char
= btChar
, /* character */
167 bt_UChar
= btUChar
, /* unsigned character */
168 bt_Short
= btShort
, /* short */
169 bt_UShort
= btUShort
, /* unsigned short */
170 bt_Int
= btInt
, /* int */
171 bt_UInt
= btUInt
, /* unsigned int */
172 bt_Long
= btLong
, /* long */
173 bt_ULong
= btULong
, /* unsigned long */
174 bt_Float
= btFloat
, /* float (real) */
175 bt_Double
= btDouble
, /* Double (real) */
176 bt_Struct
= btStruct
, /* Structure (Record) */
177 bt_Union
= btUnion
, /* Union (variant) */
178 bt_Enum
= btEnum
, /* Enumerated */
179 bt_Typedef
= btTypedef
, /* defined via a typedef, isymRef points */
180 bt_Range
= btRange
, /* subrange of int */
181 bt_Set
= btSet
, /* pascal sets */
182 bt_Complex
= btComplex
, /* fortran complex */
183 bt_DComplex
= btDComplex
, /* fortran double complex */
184 bt_Indirect
= btIndirect
, /* forward or unnamed typedef */
185 bt_FixedDec
= btFixedDec
, /* Fixed Decimal */
186 bt_FloatDec
= btFloatDec
, /* Float Decimal */
187 bt_String
= btString
, /* Varying Length Character String */
188 bt_Bit
= btBit
, /* Aligned Bit String */
189 bt_Picture
= btPicture
, /* Picture */
190 bt_Void
= btVoid
, /* void */
191 bt_Max
= btMax
/* Max basic type+1 */
194 /* Redefinition of the language codes. */
198 lang_Pascal
= langPascal
,
199 lang_Fortran
= langFortran
,
200 lang_Assembler
= langAssembler
,
201 lang_Machine
= langMachine
,
205 lang_Cobol
= langCobol
208 /* Redefinition of the debug level codes. */
210 typedef enum glevel
{
218 /* Keep track of the active scopes. */
219 typedef struct scope
{
220 struct scope
*prev
; /* previous scope */
221 ulong open_sym
; /* symbol opening scope */
222 sc_t sc
; /* storage class */
223 st_t st
; /* symbol type */
226 struct filehdr global_hdr
; /* a.out header */
228 int errors
= 0; /* # of errors */
229 int want_aux
= 0; /* print aux table */
230 int want_line
= 0; /* print line numbers */
231 int want_rfd
= 0; /* print relative file desc's */
232 int want_scope
= 0; /* print scopes for every symbol */
233 int tfile
= 0; /* no global header file */
234 int tfile_fd
; /* file descriptor of .T file */
235 off_t tfile_offset
; /* current offset in .T file */
236 scope_t
*cur_scope
= 0; /* list of active scopes */
237 scope_t
*free_scope
= 0; /* list of freed scopes */
238 HDRR sym_hdr
; /* symbolic header */
239 char *l_strings
; /* local strings */
240 char *e_strings
; /* external strings */
241 SYMR
*l_symbols
; /* local symbols */
242 EXTR
*e_symbols
; /* external symbols */
243 LINER
*lines
; /* line numbers */
244 DNR
*dense_nums
; /* dense numbers */
245 OPTR
*opt_symbols
; /* optimization symbols */
246 AUXU
*aux_symbols
; /* Auxiliary symbols */
247 char *aux_used
; /* map of which aux syms are used */
248 FDR
*file_desc
; /* file tables */
249 ulong
*rfile_desc
; /* relative file tables */
250 PDR
*proc_desc
; /* procedure tables */
252 /* Forward reference for functions. */
253 PTR_T read_seek
__proto((PTR_T
, size_t, off_t
, const char *));
254 void read_tfile
__proto((void));
255 void print_global_hdr
__proto((struct filehdr
*));
256 void print_sym_hdr
__proto((HDRR
*));
257 void print_file_desc
__proto((FDR
*, int));
258 void print_symbol
__proto((SYMR
*, int, char *, AUXU
*, int, FDR
*));
259 void print_aux
__proto((AUXU
, int, int));
260 void emit_aggregate
__proto((char *, AUXU
, AUXU
, const char *, FDR
*));
261 const char *st_to_string
__proto((st_t
));
262 const char *sc_to_string
__proto((sc_t
));
263 const char *glevel_to_string
__proto((glevel_t
));
264 const char *lang_to_string
__proto((lang_t
));
265 const char *type_to_string
__proto((AUXU
*, int, FDR
*));
271 /* Create a table of debugging stab-codes and corresponding names. */
273 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
274 struct {short code
; char string
[10];} stab_names
[] = {
280 /* Read some bytes at a specified location, and return a pointer. */
283 read_seek (ptr
, size
, offset
, context
)
284 PTR_T ptr
; /* pointer to buffer or NULL */
285 size_t size
; /* # bytes to read */
286 off_t offset
; /* offset to read at */
287 const char *context
; /* context for error message */
291 if (size
== 0) /* nothing to read */
294 if ((ptr
== (PTR_T
) 0 && (ptr
= malloc (size
)) == (PTR_T
) 0)
295 || (tfile_offset
!= offset
&& lseek (tfile_fd
, offset
, 0) == -1)
296 || (read_size
= read (tfile_fd
, ptr
, size
)) < 0)
302 if (read_size
!= size
)
304 fprintf (stderr
, "%s: read %ld bytes, expected %ld bytes\n",
305 context
, read_size
, (long) size
);
309 tfile_offset
= offset
+ size
;
314 /* Convert language code to string format. */
317 lang_to_string (lang
)
322 case langC
: return "C";
323 case langPascal
: return "Pascal";
324 case langFortran
: return "Fortran";
325 case langAssembler
: return "Assembler";
326 case langMachine
: return "Machine";
327 case langNil
: return "Nil";
328 case langAda
: return "Ada";
329 case langPl1
: return "Pl1";
330 case langCobol
: return "Cobol";
333 return "Unknown language";
337 /* Convert storage class to string. */
340 sc_to_string(storage_class
)
343 switch(storage_class
)
345 case sc_Nil
: return "Nil";
346 case sc_Text
: return "Text";
347 case sc_Data
: return "Data";
348 case sc_Bss
: return "Bss";
349 case sc_Register
: return "Register";
350 case sc_Abs
: return "Abs";
351 case sc_Undefined
: return "Undefined";
352 case sc_CdbLocal
: return "CdbLocal";
353 case sc_Bits
: return "Bits";
354 case sc_CdbSystem
: return "CdbSystem";
355 case sc_RegImage
: return "RegImage";
356 case sc_Info
: return "Info";
357 case sc_UserStruct
: return "UserStruct";
358 case sc_SData
: return "SData";
359 case sc_SBss
: return "SBss";
360 case sc_RData
: return "RData";
361 case sc_Var
: return "Var";
362 case sc_Common
: return "Common";
363 case sc_SCommon
: return "SCommon";
364 case sc_VarRegister
: return "VarRegister";
365 case sc_Variant
: return "Variant";
366 case sc_SUndefined
: return "SUndefined";
367 case sc_Init
: return "Init";
368 case sc_Max
: return "Max";
375 /* Convert symbol type to string. */
378 st_to_string(symbol_type
)
383 case st_Nil
: return "Nil";
384 case st_Global
: return "Global";
385 case st_Static
: return "Static";
386 case st_Param
: return "Param";
387 case st_Local
: return "Local";
388 case st_Label
: return "Label";
389 case st_Proc
: return "Proc";
390 case st_Block
: return "Block";
391 case st_End
: return "End";
392 case st_Member
: return "Member";
393 case st_Typedef
: return "Typedef";
394 case st_File
: return "File";
395 case st_RegReloc
: return "RegReloc";
396 case st_Forward
: return "Forward";
397 case st_StaticProc
: return "StaticProc";
398 case st_Constant
: return "Constant";
399 case st_StaParam
: return "StaticParam";
401 case st_Struct
: return "Struct";
402 case st_Union
: return "Union";
403 case st_Enum
: return "Enum";
405 case st_Str
: return "String";
406 case st_Number
: return "Number";
407 case st_Expr
: return "Expr";
408 case st_Type
: return "Type";
409 case st_Max
: return "Max";
416 /* Convert debug level to string. */
419 glevel_to_string (g_level
)
424 case GLEVEL_0
: return "G0";
425 case GLEVEL_1
: return "G1";
426 case GLEVEL_2
: return "G2";
427 case GLEVEL_3
: return "G3";
434 /* Convert the type information to string format. */
437 type_to_string (aux_ptr
, index
, fdp
)
452 static char buffer1
[1024];
453 static char buffer2
[1024];
456 char *used_ptr
= aux_used
+ (aux_ptr
- aux_symbols
);
458 for (i
= 0; i
< 7; i
++)
460 qualifiers
[i
].low_bound
= 0;
461 qualifiers
[i
].high_bound
= 0;
462 qualifiers
[i
].stride
= 0;
466 u
= aux_ptr
[index
++];
468 return "-1 (no type)";
470 basic_type
= (bt_t
) u
.ti
.bt
;
471 qualifiers
[0].type
= (tq_t
) u
.ti
.tq0
;
472 qualifiers
[1].type
= (tq_t
) u
.ti
.tq1
;
473 qualifiers
[2].type
= (tq_t
) u
.ti
.tq2
;
474 qualifiers
[3].type
= (tq_t
) u
.ti
.tq3
;
475 qualifiers
[4].type
= (tq_t
) u
.ti
.tq4
;
476 qualifiers
[5].type
= (tq_t
) u
.ti
.tq5
;
477 qualifiers
[6].type
= tq_Nil
;
480 * Go get the basic type.
484 case bt_Nil
: /* undefined */
488 case bt_Adr
: /* address - integer same size as pointer */
489 strcpy (p1
, "address");
492 case bt_Char
: /* character */
496 case bt_UChar
: /* unsigned character */
497 strcpy (p1
, "unsigned char");
500 case bt_Short
: /* short */
501 strcpy (p1
, "short");
504 case bt_UShort
: /* unsigned short */
505 strcpy (p1
, "unsigned short");
508 case bt_Int
: /* int */
512 case bt_UInt
: /* unsigned int */
513 strcpy (p1
, "unsigned int");
516 case bt_Long
: /* long */
520 case bt_ULong
: /* unsigned long */
521 strcpy (p1
, "unsigned long");
524 case bt_Float
: /* float (real) */
525 strcpy (p1
, "float");
528 case bt_Double
: /* Double (real) */
529 strcpy (p1
, "double");
532 /* Structures add 1-2 aux words:
533 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
534 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
536 case bt_Struct
: /* Structure (Record) */
537 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "struct", fdp
);
539 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
540 used_ptr
[++index
] = 1;
542 index
++; /* skip aux words */
545 /* Unions add 1-2 aux words:
546 1st word is [ST_RFDESCAPE, offset] pointer to union def;
547 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
549 case bt_Union
: /* Union */
550 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "union", fdp
);
552 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
553 used_ptr
[++index
] = 1;
555 index
++; /* skip aux words */
558 /* Enumerations add 1-2 aux words:
559 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
560 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
562 case bt_Enum
: /* Enumeration */
563 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "enum", fdp
);
565 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
566 used_ptr
[++index
] = 1;
568 index
++; /* skip aux words */
571 case bt_Typedef
: /* defined via a typedef, isymRef points */
572 strcpy (p1
, "typedef");
575 case bt_Range
: /* subrange of int */
576 strcpy (p1
, "subrange");
579 case bt_Set
: /* pascal sets */
583 case bt_Complex
: /* fortran complex */
584 strcpy (p1
, "complex");
587 case bt_DComplex
: /* fortran double complex */
588 strcpy (p1
, "double complex");
591 case bt_Indirect
: /* forward or unnamed typedef */
592 strcpy (p1
, "forward/unnamed typedef");
595 case bt_FixedDec
: /* Fixed Decimal */
596 strcpy (p1
, "fixed decimal");
599 case bt_FloatDec
: /* Float Decimal */
600 strcpy (p1
, "float decimal");
603 case bt_String
: /* Varying Length Character String */
604 strcpy (p1
, "string");
607 case bt_Bit
: /* Aligned Bit String */
611 case bt_Picture
: /* Picture */
612 strcpy (p1
, "picture");
615 case bt_Void
: /* Void */
620 sprintf (p1
, "Unknown basic type %d", (int) basic_type
);
624 p1
+= strlen (buffer1
);
627 * If this is a bitfield, get the bitsize.
634 bitsize
= aux_ptr
[index
++].width
;
635 sprintf (p1
, " : %d", bitsize
);
636 p1
+= strlen (buffer1
);
641 * Deal with any qualifiers.
643 if (qualifiers
[0].type
!= tq_Nil
)
646 * Snarf up any array bounds in the correct order. Arrays
647 * store 5 successive words in the aux. table:
648 * word 0 RNDXR to type of the bounds (ie, int)
649 * word 1 Current file descriptor index
651 * word 3 high bound (or -1 if [])
652 * word 4 stride size in bits
654 for (i
= 0; i
< 7; i
++)
656 if (qualifiers
[i
].type
== tq_Array
)
658 qualifiers
[i
].low_bound
= aux_ptr
[index
+2].dnLow
;
659 qualifiers
[i
].high_bound
= aux_ptr
[index
+3].dnHigh
;
660 qualifiers
[i
].stride
= aux_ptr
[index
+4].width
;
662 used_ptr
[index
+1] = 1;
663 used_ptr
[index
+2] = 1;
664 used_ptr
[index
+3] = 1;
665 used_ptr
[index
+4] = 1;
671 * Now print out the qualifiers.
673 for (i
= 0; i
< 6; i
++)
675 switch (qualifiers
[i
].type
)
682 strcpy (p2
, "ptr to ");
683 p2
+= sizeof ("ptr to ")-1;
687 strcpy (p2
, "volatile ");
688 p2
+= sizeof ("volatile ")-1;
693 p2
+= sizeof ("far ")-1;
697 strcpy (p2
, "func. ret. ");
698 p2
+= sizeof ("func. ret. ");
706 /* Print array bounds reversed (ie, in the order the C
707 programmer writes them). C is such a fun language.... */
709 while (i
< 5 && qualifiers
[i
+1].type
== tq_Array
)
712 for (j
= i
; j
>= first_array
; j
--)
714 strcpy (p2
, "array [");
715 p2
+= sizeof ("array [")-1;
716 if (qualifiers
[j
].low_bound
!= 0)
718 "%ld:%ld {%ld bits}",
719 (long) qualifiers
[j
].low_bound
,
720 (long) qualifiers
[j
].high_bound
,
721 (long) qualifiers
[j
].stride
);
723 else if (qualifiers
[j
].high_bound
!= -1)
726 (long) (qualifiers
[j
].high_bound
+ 1),
727 (long) (qualifiers
[j
].stride
));
730 sprintf (p2
, " {%ld bits}", (long) (qualifiers
[j
].stride
));
733 strcpy (p2
, "] of ");
734 p2
+= sizeof ("] of ")-1;
742 strcpy (p2
, buffer1
);
747 /* Print out the global file header for object files. */
750 print_global_hdr (ptr
)
753 char *time
= ctime ((time_t *)&ptr
->f_timdat
);
754 ushort flags
= ptr
->f_flags
;
756 printf("Global file header:\n");
757 printf(" %-*s 0x%x\n", 24, "magic number", (ushort
) ptr
->f_magic
);
758 printf(" %-*s %d\n", 24, "# sections", (int) ptr
->f_nscns
);
759 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr
->f_timdat
, time
);
760 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr
->f_symptr
);
761 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr
->f_nsyms
);
762 printf(" %-*s %ld\n", 24, "optional header", (long) ptr
->f_opthdr
);
763 printf(" %-*s 0x%x", 24, "flags", (ushort
) flags
);
765 if ((flags
& F_RELFLG
) != 0)
766 printf (", F_RELFLG");
768 if ((flags
& F_EXEC
) != 0)
771 if ((flags
& F_LNNO
) != 0)
774 if ((flags
& F_LSYMS
) != 0)
775 printf (", F_LSYMS");
777 if ((flags
& F_MINMAL
) != 0)
778 printf (", F_MINMAL");
780 if ((flags
& F_UPDATE
) != 0)
781 printf (", F_UPDATE");
783 if ((flags
& F_SWABD
) != 0)
784 printf (", F_SWABD");
786 if ((flags
& F_AR16WR
) != 0)
787 printf (", F_AR16WR");
789 if ((flags
& F_AR32WR
) != 0)
790 printf (", F_AR32WR");
792 if ((flags
& F_AR32W
) != 0)
793 printf (", F_AR32W");
795 if ((flags
& F_PATCH
) != 0)
796 printf (", F_PATCH/F_NODF");
802 /* Print out the symbolic header. */
805 print_sym_hdr (sym_ptr
)
810 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
811 sym_ptr
->magic
& 0xffff,
812 (sym_ptr
->vstamp
& 0xffff) >> 8,
813 sym_ptr
->vstamp
& 0xff);
815 printf(" %-*s %11s %11s %11s\n", width
, "Info", "Offset", "Number", "Bytes");
816 printf(" %-*s %11s %11s %11s\n", width
, "====", "======", "======", "=====\n");
818 printf(" %-*s %11ld %11ld %11ld [%d]\n", width
, "Line numbers",
819 (long) sym_ptr
->cbLineOffset
,
820 (long) sym_ptr
->cbLine
,
821 (long) sym_ptr
->cbLine
,
822 (int) sym_ptr
->ilineMax
);
824 printf(" %-*s %11ld %11ld %11ld\n", width
, "Dense numbers",
825 (long) sym_ptr
->cbDnOffset
,
826 (long) sym_ptr
->idnMax
,
827 (long) (sym_ptr
->idnMax
* sizeof (DNR
)));
829 printf(" %-*s %11ld %11ld %11ld\n", width
, "Procedures Tables",
830 (long) sym_ptr
->cbPdOffset
,
831 (long) sym_ptr
->ipdMax
,
832 (long) (sym_ptr
->ipdMax
* sizeof (PDR
)));
834 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Symbols",
835 (long) sym_ptr
->cbSymOffset
,
836 (long) sym_ptr
->isymMax
,
837 (long) (sym_ptr
->isymMax
* sizeof (SYMR
)));
839 printf(" %-*s %11ld %11ld %11ld\n", width
, "Optimization Symbols",
840 (long) sym_ptr
->cbOptOffset
,
841 (long) sym_ptr
->ioptMax
,
842 (long) (sym_ptr
->ioptMax
* sizeof (OPTR
)));
844 printf(" %-*s %11ld %11ld %11ld\n", width
, "Auxiliary Symbols",
845 (long) sym_ptr
->cbAuxOffset
,
846 (long) sym_ptr
->iauxMax
,
847 (long) (sym_ptr
->iauxMax
* sizeof (AUXU
)));
849 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Strings",
850 (long) sym_ptr
->cbSsOffset
,
851 (long) sym_ptr
->issMax
,
852 (long) sym_ptr
->issMax
);
854 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Strings",
855 (long) sym_ptr
->cbSsExtOffset
,
856 (long) sym_ptr
->issExtMax
,
857 (long) sym_ptr
->issExtMax
);
859 printf(" %-*s %11ld %11ld %11ld\n", width
, "File Tables",
860 (long) sym_ptr
->cbFdOffset
,
861 (long) sym_ptr
->ifdMax
,
862 (long) (sym_ptr
->ifdMax
* sizeof (FDR
)));
864 printf(" %-*s %11ld %11ld %11ld\n", width
, "Relative Files",
865 (long) sym_ptr
->cbRfdOffset
,
866 (long) sym_ptr
->crfd
,
867 (long) (sym_ptr
->crfd
* sizeof (ulong
)));
869 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Symbols",
870 (long) sym_ptr
->cbExtOffset
,
871 (long) sym_ptr
->iextMax
,
872 (long) (sym_ptr
->iextMax
* sizeof (EXTR
)));
876 /* Print out a symbol. */
879 print_symbol (sym_ptr
, number
, strbase
, aux_base
, ifd
, fdp
)
887 sc_t storage_class
= (sc_t
) sym_ptr
->sc
;
888 st_t symbol_type
= (st_t
) sym_ptr
->st
;
889 ulong index
= sym_ptr
->index
;
890 char *used_ptr
= aux_used
+ (aux_base
- aux_symbols
);
893 printf ("\n Symbol# %d: \"%s\"\n", number
, sym_ptr
->iss
+ strbase
);
895 if (aux_base
!= (AUXU
*) 0 && index
!= indexNil
)
904 printf (" End+1 symbol: %ld\n", index
);
907 if (free_scope
== (scope_t
*) 0)
908 scope_ptr
= (scope_t
*) xmalloc (sizeof (scope_t
));
911 scope_ptr
= free_scope
;
912 free_scope
= scope_ptr
->prev
;
914 scope_ptr
->open_sym
= number
;
915 scope_ptr
->st
= symbol_type
;
916 scope_ptr
->sc
= storage_class
;
917 scope_ptr
->prev
= cur_scope
;
918 cur_scope
= scope_ptr
;
923 if (storage_class
== sc_Text
|| storage_class
== sc_Info
)
924 printf (" First symbol: %ld\n", index
);
928 printf (" First symbol: %ld\n", (long) aux_base
[index
].isym
);
933 if (cur_scope
== (scope_t
*) 0)
934 printf (" Can't pop end scope\n");
937 scope_ptr
= cur_scope
;
938 cur_scope
= scope_ptr
->prev
;
939 scope_ptr
->prev
= free_scope
;
940 free_scope
= scope_ptr
;
947 if (MIPS_IS_STAB(sym_ptr
))
949 else if (ifd
== -1) /* local symbol */
951 used_ptr
[index
] = used_ptr
[index
+1] = 1;
952 printf (" End+1 symbol: %-7ld Type: %s\n",
953 (long) aux_base
[index
].isym
,
954 type_to_string (aux_base
, index
+1, fdp
));
956 else /* global symbol */
957 printf (" Local symbol: %ld\n", index
);
961 if (free_scope
== (scope_t
*) 0)
962 scope_ptr
= (scope_t
*) xmalloc (sizeof (scope_t
));
965 scope_ptr
= free_scope
;
966 free_scope
= scope_ptr
->prev
;
968 scope_ptr
->open_sym
= number
;
969 scope_ptr
->st
= symbol_type
;
970 scope_ptr
->sc
= storage_class
;
971 scope_ptr
->prev
= cur_scope
;
972 cur_scope
= scope_ptr
;
980 printf (" End+1 symbol: %lu\n", index
);
985 if (!MIPS_IS_STAB (sym_ptr
))
988 printf (" Type: %s\n",
989 type_to_string (aux_base
, index
, fdp
));
996 printf (" Scopes: ");
997 if (cur_scope
== (scope_t
*) 0)
1001 for (scope_ptr
= cur_scope
;
1002 scope_ptr
!= (scope_t
*) 0;
1003 scope_ptr
= scope_ptr
->prev
)
1006 if (scope_ptr
->st
== st_Proc
|| scope_ptr
->st
== st_StaticProc
)
1008 else if (scope_ptr
->st
== st_File
)
1010 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Text
)
1012 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Info
)
1017 printf (" %ld [%s]", scope_ptr
->open_sym
, class);
1023 printf (" Value: %-13ld ",
1024 (long)sym_ptr
->value
);
1026 printf ("String index: %ld\n", (long)sym_ptr
->iss
);
1028 printf ("String index: %-11ld Ifd: %d\n",
1029 (long)sym_ptr
->iss
, ifd
);
1031 printf (" Symbol type: %-11sStorage class: %-11s",
1032 st_to_string (symbol_type
), sc_to_string (storage_class
));
1034 if (MIPS_IS_STAB(sym_ptr
))
1036 register int i
= sizeof(stab_names
) / sizeof(stab_names
[0]);
1037 const char *stab_name
= "stab";
1038 short code
= MIPS_UNMARK_STAB(sym_ptr
->index
);
1040 if (stab_names
[i
].code
== code
)
1042 stab_name
= stab_names
[i
].string
;
1045 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr
->index
, stab_name
);
1047 else if (sym_ptr
->st
== stLabel
&& sym_ptr
->index
!= indexNil
)
1048 printf ("Index: %ld (line#)\n", (long)sym_ptr
->index
);
1050 printf ("Index: %ld\n", (long)sym_ptr
->index
);
1055 /* Print out a word from the aux. table in various formats. */
1058 print_aux (u
, auxi
, used
)
1063 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1064 (used
) ? " " : "* ",
1068 (long) u
.rndx
.index
,
1081 /* Write aggregate information to a string. */
1084 emit_aggregate (string
, u
, u2
, which
, fdp
)
1091 unsigned int ifd
= u
.rndx
.rfd
;
1092 unsigned int index
= u
.rndx
.index
;
1095 if (ifd
== ST_RFDESCAPE
)
1098 /* An ifd of -1 is an opaque type. An escaped index of 0 is a
1099 struct return type of a procedure compiled without -g. */
1100 if (ifd
== 0xffffffff
1101 || (u
.rndx
.rfd
== ST_RFDESCAPE
&& index
== 0))
1102 name
= "<undefined>";
1103 else if (index
== indexNil
)
1107 if (fdp
== 0 || sym_hdr
.crfd
== 0)
1108 fdp
= &file_desc
[ifd
];
1110 fdp
= &file_desc
[rfile_desc
[fdp
->rfdBase
+ ifd
]];
1111 name
= &l_strings
[fdp
->issBase
+ l_symbols
[index
+ fdp
->isymBase
].iss
];
1115 "%s %s { ifd = %u, index = %u }",
1116 which
, name
, ifd
, index
);
1120 /* Print out information about a file descriptor, and the symbols,
1121 procedures, and line numbers within it. */
1124 print_file_desc (fdp
, number
)
1134 str_base
= l_strings
+ fdp
->issBase
;
1135 aux_base
= aux_symbols
+ fdp
->iauxBase
;
1136 used_base
= aux_used
+ (aux_base
- aux_symbols
);
1138 printf ("\nFile #%d, \"%s\"\n\n",
1140 fdp
->rss
!= issNil
? str_base
+ fdp
->rss
: "<unknown>");
1142 printf (" Name index = %-10ld Readin = %s\n",
1143 (long) fdp
->rss
, (fdp
->fReadin
) ? "Yes" : "No");
1145 printf (" Merge = %-10s Endian = %s\n",
1146 (fdp
->fMerge
) ? "Yes" : "No",
1147 (fdp
->fBigendian
) ? "BIG" : "LITTLE");
1149 printf (" Debug level = %-10s Language = %s\n",
1150 glevel_to_string (fdp
->glevel
),
1151 lang_to_string((lang_t
) fdp
->lang
));
1153 printf (" Adr = 0x%08lx\n\n", (long) fdp
->adr
);
1155 printf(" %-*s %11s %11s %11s %11s\n", width
, "Info", "Start", "Number", "Size", "Offset");
1156 printf(" %-*s %11s %11s %11s %11s\n", width
, "====", "=====", "======", "====", "======");
1158 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1159 width
, "Local strings",
1160 (ulong
) fdp
->issBase
,
1163 (ulong
) (fdp
->issBase
+ sym_hdr
.cbSsOffset
));
1165 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1166 width
, "Local symbols",
1167 (ulong
) fdp
->isymBase
,
1169 (ulong
) (fdp
->csym
* sizeof (SYMR
)),
1170 (ulong
) (fdp
->isymBase
* sizeof (SYMR
) + sym_hdr
.cbSymOffset
));
1172 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1173 width
, "Line numbers",
1174 (ulong
) fdp
->cbLineOffset
,
1176 (ulong
) fdp
->cbLine
,
1177 (ulong
) (fdp
->cbLineOffset
+ sym_hdr
.cbLineOffset
));
1179 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1180 width
, "Optimization symbols",
1181 (ulong
) fdp
->ioptBase
,
1183 (ulong
) (fdp
->copt
* sizeof (OPTR
)),
1184 (ulong
) (fdp
->ioptBase
* sizeof (OPTR
) + sym_hdr
.cbOptOffset
));
1186 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1187 width
, "Procedures",
1188 (ulong
) fdp
->ipdFirst
,
1190 (ulong
) (fdp
->cpd
* sizeof (PDR
)),
1191 (ulong
) (fdp
->ipdFirst
* sizeof (PDR
) + sym_hdr
.cbPdOffset
));
1193 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1194 width
, "Auxiliary symbols",
1195 (ulong
) fdp
->iauxBase
,
1197 (ulong
) (fdp
->caux
* sizeof (AUXU
)),
1198 (ulong
) (fdp
->iauxBase
* sizeof(AUXU
) + sym_hdr
.cbAuxOffset
));
1200 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1201 width
, "Relative Files",
1202 (ulong
) fdp
->rfdBase
,
1204 (ulong
) (fdp
->crfd
* sizeof (ulong
)),
1205 (ulong
) (fdp
->rfdBase
* sizeof(ulong
) + sym_hdr
.cbRfdOffset
));
1208 if (want_scope
&& cur_scope
!= (scope_t
*) 0)
1209 printf ("\n Warning scope does not start at 0!\n");
1212 * print the info about the symbol table.
1214 printf ("\n There are %lu local symbols, starting at %lu\n",
1216 (ulong
) (fdp
->isymBase
+ sym_hdr
.cbSymOffset
));
1218 for(symi
= fdp
->isymBase
; symi
< (fdp
->csym
+ fdp
->isymBase
); symi
++)
1219 print_symbol (&l_symbols
[symi
],
1220 symi
- fdp
->isymBase
,
1226 if (want_scope
&& cur_scope
!= (scope_t
*) 0)
1227 printf ("\n Warning scope does not end at 0!\n");
1230 * print the aux. table if desired.
1233 if (want_aux
&& fdp
->caux
!= 0)
1237 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1239 (ulong
) (fdp
->iauxBase
+ sym_hdr
.cbAuxOffset
));
1241 for (auxi
= fdp
->iauxBase
; auxi
< (fdp
->caux
+ fdp
->iauxBase
); auxi
++)
1242 print_aux (aux_base
[auxi
], auxi
, used_base
[auxi
]);
1246 * print the relative file descriptors.
1248 if (want_rfd
&& fdp
->crfd
!= 0)
1252 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1254 (ulong
) fdp
->rfdBase
);
1256 rfd_ptr
= rfile_desc
+ fdp
->rfdBase
;
1257 for (i
= 0; i
< (ulong
) fdp
->crfd
; i
++)
1259 printf ("\t#%-5ld %11ld, 0x%08lx\n", i
, *rfd_ptr
, *rfd_ptr
);
1265 * do the procedure descriptors.
1267 printf ("\n There are %lu procedure descriptor entries, ", (ulong
) fdp
->cpd
);
1268 printf ("starting at %lu.\n", (ulong
) fdp
->ipdFirst
);
1270 for (pdi
= fdp
->ipdFirst
; pdi
< (fdp
->cpd
+ fdp
->ipdFirst
); pdi
++)
1272 PDR
*proc_ptr
= &proc_desc
[pdi
];
1273 printf ("\n\tProcedure descriptor %d:\n", (pdi
- fdp
->ipdFirst
));
1276 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1277 (long) l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
,
1278 l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
+ str_base
);
1280 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1281 (long) proc_ptr
->regmask
,
1282 (long) proc_ptr
->regoffset
,
1283 (long) proc_ptr
->fregmask
,
1284 (long) proc_ptr
->fregoffset
);
1286 printf ("\t .frame $%d,%ld,$%d\n",
1287 (int) proc_ptr
->framereg
,
1288 (long) proc_ptr
->frameoffset
,
1289 (int) proc_ptr
->pcreg
);
1291 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1292 (long) proc_ptr
->iopt
,
1293 (long) proc_ptr
->isym
);
1295 printf ("\t First line # = %-11ld Last line # = %ld\n",
1296 (long) proc_ptr
->lnLow
,
1297 (long) proc_ptr
->lnHigh
);
1299 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1300 (long) proc_ptr
->cbLineOffset
,
1301 (long) proc_ptr
->adr
);
1304 * print the line number entries.
1307 if (want_line
&& fdp
->cline
!= 0)
1310 long cur_line
= proc_ptr
->lnLow
;
1311 uchar
*line_ptr
= (((uchar
*)lines
) + proc_ptr
->cbLineOffset
1312 + fdp
->cbLineOffset
);
1315 if (pdi
== fdp
->cpd
+ fdp
->ipdFirst
- 1) /* last procedure */
1316 line_end
= ((uchar
*)lines
) + fdp
->cbLine
+ fdp
->cbLineOffset
;
1317 else /* not last proc. */
1318 line_end
= (((uchar
*)lines
) + proc_desc
[pdi
+1].cbLineOffset
1319 + fdp
->cbLineOffset
);
1321 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1322 (ulong
) (line_end
- line_ptr
),
1323 (ulong
) (fdp
->ilineBase
+ sym_hdr
.cbLineOffset
));
1325 while (line_ptr
< line_end
)
1326 { /* sign extend nibble */
1327 delta
= ((*line_ptr
>> 4) ^ 0x8) - 0x8;
1328 count
= (*line_ptr
& 0xf) + 1;
1333 delta
= (((line_ptr
[1]) & 0xff) << 8) + ((line_ptr
[2]) & 0xff);
1334 delta
= (delta
^ 0x8000) - 0x8000;
1339 printf ("\t Line %11ld, delta %5d, count %2d\n",
1349 /* Read in the portions of the .T file that we will print out. */
1352 read_tfile
__proto((void))
1355 off_t sym_hdr_offset
= 0;
1357 (void) read_seek ((PTR_T
) &magic
, sizeof (magic
), (off_t
) 0, "Magic number");
1360 /* Print out the global header, since this is not a T-file. */
1362 (void) read_seek ((PTR_T
) &global_hdr
, sizeof (global_hdr
), (off_t
) 0,
1363 "Global file header");
1365 print_global_hdr (&global_hdr
);
1367 if (global_hdr
.f_symptr
== 0)
1369 printf ("No symbolic header, Goodbye!\n");
1373 sym_hdr_offset
= global_hdr
.f_symptr
;
1376 (void) read_seek ((PTR_T
) &sym_hdr
,
1381 print_sym_hdr (&sym_hdr
);
1383 lines
= (LINER
*) read_seek ((PTR_T
) 0,
1385 sym_hdr
.cbLineOffset
,
1388 dense_nums
= (DNR
*) read_seek ((PTR_T
) 0,
1389 sym_hdr
.idnMax
* sizeof (DNR
),
1393 proc_desc
= (PDR
*) read_seek ((PTR_T
) 0,
1394 sym_hdr
.ipdMax
* sizeof (PDR
),
1396 "Procedure tables");
1398 l_symbols
= (SYMR
*) read_seek ((PTR_T
) 0,
1399 sym_hdr
.isymMax
* sizeof (SYMR
),
1400 sym_hdr
.cbSymOffset
,
1403 opt_symbols
= (OPTR
*) read_seek ((PTR_T
) 0,
1404 sym_hdr
.ioptMax
* sizeof (OPTR
),
1405 sym_hdr
.cbOptOffset
,
1406 "Optimization symbols");
1408 aux_symbols
= (AUXU
*) read_seek ((PTR_T
) 0,
1409 sym_hdr
.iauxMax
* sizeof (AUXU
),
1410 sym_hdr
.cbAuxOffset
,
1411 "Auxiliary symbols");
1413 if (sym_hdr
.iauxMax
> 0)
1414 aux_used
= xcalloc (sym_hdr
.iauxMax
, 1);
1416 l_strings
= (char *) read_seek ((PTR_T
) 0,
1419 "Local string table");
1421 e_strings
= (char *) read_seek ((PTR_T
) 0,
1423 sym_hdr
.cbSsExtOffset
,
1424 "External string table");
1426 file_desc
= (FDR
*) read_seek ((PTR_T
) 0,
1427 sym_hdr
.ifdMax
* sizeof (FDR
),
1431 rfile_desc
= (ulong
*) read_seek ((PTR_T
) 0,
1432 sym_hdr
.crfd
* sizeof (ulong
),
1433 sym_hdr
.cbRfdOffset
,
1434 "Relative file tables");
1436 e_symbols
= (EXTR
*) read_seek ((PTR_T
) 0,
1437 sym_hdr
.iextMax
* sizeof (EXTR
),
1438 sym_hdr
.cbExtOffset
,
1439 "External symbols");
1444 extern int main
PROTO ((int, char **));
1456 while ((opt
= getopt (argc
, argv
, "alrst")) != EOF
)
1459 default: errors
++; break;
1460 case 'a': want_aux
++; break; /* print aux table */
1461 case 'l': want_line
++; break; /* print line numbers */
1462 case 'r': want_rfd
++; break; /* print relative fd's */
1463 case 's': want_scope
++; break; /* print scope info */
1464 case 't': tfile
++; break; /* this is a tfile (without header), and not a .o */
1467 if (errors
|| optind
!= argc
- 1)
1469 fprintf (stderr
, "Calling Sequence:\n");
1470 fprintf (stderr
, "\t%s [-alrst] <object-or-T-file>\n", argv
[0]);
1471 fprintf (stderr
, "\n");
1472 fprintf (stderr
, "switches:\n");
1473 fprintf (stderr
, "\t-a Print out auxiliary table.\n");
1474 fprintf (stderr
, "\t-l Print out line numbers.\n");
1475 fprintf (stderr
, "\t-r Print out relative file descriptors.\n");
1476 fprintf (stderr
, "\t-s Print out the current scopes for an item.\n");
1477 fprintf (stderr
, "\t-t Assume there is no global header (ie, a T-file).\n");
1482 * Open and process the input file.
1484 tfile_fd
= open (argv
[optind
], O_RDONLY
);
1487 perror (argv
[optind
]);
1494 * Print any global aux words if any.
1498 long last_aux_in_use
;
1500 if (sym_hdr
.ifdMax
!= 0 && file_desc
[0].iauxBase
!= 0)
1502 printf ("\nGlobal auxiliary entries before first file:\n");
1503 for (i
= 0; i
< file_desc
[0].iauxBase
; i
++)
1504 print_aux (aux_symbols
[i
], 0, aux_used
[i
]);
1507 if (sym_hdr
.ifdMax
== 0)
1508 last_aux_in_use
= 0;
1511 = (file_desc
[sym_hdr
.ifdMax
-1].iauxBase
1512 + file_desc
[sym_hdr
.ifdMax
-1].caux
- 1);
1514 if (last_aux_in_use
< sym_hdr
.iauxMax
-1)
1516 printf ("\nGlobal auxiliary entries after last file:\n");
1517 for (i
= last_aux_in_use
; i
< sym_hdr
.iauxMax
; i
++)
1518 print_aux (aux_symbols
[i
], i
- last_aux_in_use
, aux_used
[i
]);
1523 * Print the information for each file.
1525 for (i
= 0; i
< sym_hdr
.ifdMax
; i
++)
1526 print_file_desc (&file_desc
[i
], i
);
1529 * Print the external symbols.
1531 want_scope
= 0; /* scope info is meaning for extern symbols */
1532 printf ("\nThere are %lu external symbols, starting at %lu\n",
1533 (ulong
) sym_hdr
.iextMax
,
1534 (ulong
) sym_hdr
.cbExtOffset
);
1536 for(i
= 0; i
< sym_hdr
.iextMax
; i
++)
1537 print_symbol (&e_symbols
[i
].asym
, i
, e_strings
,
1538 aux_symbols
+ file_desc
[e_symbols
[i
].ifd
].iauxBase
,
1540 &file_desc
[e_symbols
[i
].ifd
]);
1543 * Print unused aux symbols now.
1550 for (i
= 0; i
< sym_hdr
.iauxMax
; i
++)
1556 printf ("\nThe following auxiliary table entries were unused:\n\n");
1560 printf (" #%-5d %11ld 0x%08lx %s\n",
1562 (long) aux_symbols
[i
].isym
,
1563 (long) aux_symbols
[i
].isym
,
1564 type_to_string (aux_symbols
, i
, (FDR
*) 0));
1576 fprintf (stderr
, "mips-tdump internal error");