1 /* Read and manage MIPS symbol tables from object modules.
2 Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
3 Contributed by hartzell@boulder.colorado.edu,
4 Rewritten by meissner@osf.org.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
33 #include "mips/a.out.h"
34 #endif /* CROSS_COMPILE */
37 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
38 and mips-tdump.c to print them out. This is used on the Alpha,
39 which does not include mips.h.
41 These must match the corresponding definitions in gdb/mipsread.c.
42 Unfortunately, gcc and gdb do not currently share any directories. */
44 #define CODE_MASK 0x8F300
45 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
46 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
47 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
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
64 fprintf(stderr
, "%s\n", s
);
65 exit(FATAL_EXIT_CODE
);
68 /* Same as `malloc' but report error if no memory available. */
69 /* Do this before size_t is fiddled with so it matches the prototype
75 register PTR value
= (PTR
) malloc (size
);
77 fatal ("Virtual memory exhausted.");
81 /* Due to size_t being defined in sys/types.h and different
82 in stddef.h, we have to do this by hand..... Note, these
83 types are correct for MIPS based systems, and may not be
84 correct for other systems. */
90 /* Redefinition of storage classes as an enumeration for better
94 #define stStaParam 16 /* Fortran static parameters */
98 #define btVoid 26 /* void basic type */
102 sc_Nil
= scNil
, /* no storage class */
103 sc_Text
= scText
, /* text symbol */
104 sc_Data
= scData
, /* initialized data symbol */
105 sc_Bss
= scBss
, /* un-initialized data symbol */
106 sc_Register
= scRegister
, /* value of symbol is register number */
107 sc_Abs
= scAbs
, /* value of symbol is absolute */
108 sc_Undefined
= scUndefined
, /* who knows? */
109 sc_CdbLocal
= scCdbLocal
, /* variable's value is IN se->va.?? */
110 sc_Bits
= scBits
, /* this is a bit field */
111 sc_CdbSystem
= scCdbSystem
, /* var's value is IN CDB's address space */
112 sc_RegImage
= scRegImage
, /* register value saved on stack */
113 sc_Info
= scInfo
, /* symbol contains debugger information */
114 sc_UserStruct
= scUserStruct
, /* addr in struct user for current process */
115 sc_SData
= scSData
, /* load time only small data */
116 sc_SBss
= scSBss
, /* load time only small common */
117 sc_RData
= scRData
, /* load time only read only data */
118 sc_Var
= scVar
, /* Var parameter (fortran,pascal) */
119 sc_Common
= scCommon
, /* common variable */
120 sc_SCommon
= scSCommon
, /* small common */
121 sc_VarRegister
= scVarRegister
, /* Var parameter in a register */
122 sc_Variant
= scVariant
, /* Variant record */
123 sc_SUndefined
= scSUndefined
, /* small undefined(external) data */
124 sc_Init
= scInit
, /* .init section symbol */
125 sc_Max
= scMax
/* Max storage class+1 */
128 /* Redefinition of symbol type. */
131 st_Nil
= stNil
, /* Nuthin' special */
132 st_Global
= stGlobal
, /* external symbol */
133 st_Static
= stStatic
, /* static */
134 st_Param
= stParam
, /* procedure argument */
135 st_Local
= stLocal
, /* local variable */
136 st_Label
= stLabel
, /* label */
137 st_Proc
= stProc
, /* " " Procedure */
138 st_Block
= stBlock
, /* beginning of block */
139 st_End
= stEnd
, /* end (of anything) */
140 st_Member
= stMember
, /* member (of anything - struct/union/enum */
141 st_Typedef
= stTypedef
, /* type definition */
142 st_File
= stFile
, /* file name */
143 st_RegReloc
= stRegReloc
, /* register relocation */
144 st_Forward
= stForward
, /* forwarding address */
145 st_StaticProc
= stStaticProc
, /* load time only static procs */
146 st_StaParam
= stStaParam
, /* Fortran static parameters */
147 st_Constant
= stConstant
, /* const */
149 st_Struct
= stStruct
, /* struct */
150 st_Union
= stUnion
, /* union */
151 st_Enum
= stEnum
, /* enum */
153 st_Str
= stStr
, /* string */
154 st_Number
= stNumber
, /* pure number (ie. 4 NOR 2+2) */
155 st_Expr
= stExpr
, /* 2+2 vs. 4 */
156 st_Type
= stType
, /* post-coercion SER */
157 st_Max
= stMax
/* max type+1 */
160 /* Redefinition of type qualifiers. */
163 tq_Nil
= tqNil
, /* bt is what you see */
164 tq_Ptr
= tqPtr
, /* pointer */
165 tq_Proc
= tqProc
, /* procedure */
166 tq_Array
= tqArray
, /* duh */
167 tq_Far
= tqFar
, /* longer addressing - 8086/8 land */
168 tq_Vol
= tqVol
, /* volatile */
169 tq_Max
= tqMax
/* Max type qualifier+1 */
172 /* Redefinition of basic types. */
175 bt_Nil
= btNil
, /* undefined */
176 bt_Adr
= btAdr
, /* address - integer same size as pointer */
177 bt_Char
= btChar
, /* character */
178 bt_UChar
= btUChar
, /* unsigned character */
179 bt_Short
= btShort
, /* short */
180 bt_UShort
= btUShort
, /* unsigned short */
181 bt_Int
= btInt
, /* int */
182 bt_UInt
= btUInt
, /* unsigned int */
183 bt_Long
= btLong
, /* long */
184 bt_ULong
= btULong
, /* unsigned long */
185 bt_Float
= btFloat
, /* float (real) */
186 bt_Double
= btDouble
, /* Double (real) */
187 bt_Struct
= btStruct
, /* Structure (Record) */
188 bt_Union
= btUnion
, /* Union (variant) */
189 bt_Enum
= btEnum
, /* Enumerated */
190 bt_Typedef
= btTypedef
, /* defined via a typedef, isymRef points */
191 bt_Range
= btRange
, /* subrange of int */
192 bt_Set
= btSet
, /* pascal sets */
193 bt_Complex
= btComplex
, /* fortran complex */
194 bt_DComplex
= btDComplex
, /* fortran double complex */
195 bt_Indirect
= btIndirect
, /* forward or unnamed typedef */
196 bt_FixedDec
= btFixedDec
, /* Fixed Decimal */
197 bt_FloatDec
= btFloatDec
, /* Float Decimal */
198 bt_String
= btString
, /* Varying Length Character String */
199 bt_Bit
= btBit
, /* Aligned Bit String */
200 bt_Picture
= btPicture
, /* Picture */
201 bt_Void
= btVoid
, /* void */
202 bt_Max
= btMax
/* Max basic type+1 */
205 /* Redefinition of the language codes. */
209 lang_Pascal
= langPascal
,
210 lang_Fortran
= langFortran
,
211 lang_Assembler
= langAssembler
,
212 lang_Machine
= langMachine
,
216 lang_Cobol
= langCobol
219 /* Redefinition of the debug level codes. */
221 typedef enum glevel
{
229 /* Keep track of the active scopes. */
230 typedef struct scope
{
231 struct scope
*prev
; /* previous scope */
232 ulong open_sym
; /* symbol opening scope */
233 sc_t sc
; /* storage class */
234 st_t st
; /* symbol type */
237 struct filehdr global_hdr
; /* a.out header */
239 int errors
= 0; /* # of errors */
240 int want_aux
= 0; /* print aux table */
241 int want_line
= 0; /* print line numbers */
242 int want_rfd
= 0; /* print relative file desc's */
243 int want_scope
= 0; /* print scopes for every symbol */
244 int tfile
= 0; /* no global header file */
245 int tfile_fd
; /* file descriptor of .T file */
246 off_t tfile_offset
; /* current offset in .T file */
247 scope_t
*cur_scope
= 0; /* list of active scopes */
248 scope_t
*free_scope
= 0; /* list of freed scopes */
249 HDRR sym_hdr
; /* symbolic header */
250 char *l_strings
; /* local strings */
251 char *e_strings
; /* external strings */
252 SYMR
*l_symbols
; /* local symbols */
253 EXTR
*e_symbols
; /* external symbols */
254 LINER
*lines
; /* line numbers */
255 DNR
*dense_nums
; /* dense numbers */
256 OPTR
*opt_symbols
; /* optimization symbols */
257 AUXU
*aux_symbols
; /* Auxiliary symbols */
258 char *aux_used
; /* map of which aux syms are used */
259 FDR
*file_desc
; /* file tables */
260 ulong
*rfile_desc
; /* relative file tables */
261 PDR
*proc_desc
; /* procedure tables */
263 /* Forward reference for functions. */
264 PTR_T read_seek
__proto((PTR_T
, size_t, off_t
, const char *));
265 void read_tfile
__proto((void));
266 void print_global_hdr
__proto((struct filehdr
*));
267 void print_sym_hdr
__proto((HDRR
*));
268 void print_file_desc
__proto((FDR
*, int));
269 void print_symbol
__proto((SYMR
*, int, char *, AUXU
*, int, FDR
*));
270 void print_aux
__proto((AUXU
, int, int));
271 void emit_aggregate
__proto((char *, AUXU
, AUXU
, const char *, FDR
*));
272 const char *st_to_string
__proto((st_t
));
273 const char *sc_to_string
__proto((sc_t
));
274 const char *glevel_to_string
__proto((glevel_t
));
275 const char *lang_to_string
__proto((lang_t
));
276 const char *type_to_string
__proto((AUXU
*, int, FDR
*));
279 # ifdef NEED_DECLARATION_MALLOC
280 extern PTR_T malloc
__proto((size_t));
282 # ifdef NEED_DECLARATION_CALLOC
283 extern PTR_T calloc
__proto((size_t, size_t));
285 # ifdef NEED_DECLARATION_REALLOC
286 extern PTR_T realloc
__proto((PTR_T
, size_t));
294 /* Create a table of debugging stab-codes and corresponding names. */
296 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
297 struct {short code
; char string
[10];} stab_names
[] = {
303 /* Read some bytes at a specified location, and return a pointer. */
306 read_seek (ptr
, size
, offset
, context
)
307 PTR_T ptr
; /* pointer to buffer or NULL */
308 size_t size
; /* # bytes to read */
309 off_t offset
; /* offset to read at */
310 const char *context
; /* context for error message */
314 if (size
== 0) /* nothing to read */
317 if ((ptr
== (PTR_T
) 0 && (ptr
= malloc (size
)) == (PTR_T
) 0)
318 || (tfile_offset
!= offset
&& lseek (tfile_fd
, offset
, 0) == -1)
319 || (read_size
= read (tfile_fd
, ptr
, size
)) < 0)
325 if (read_size
!= size
)
327 fprintf (stderr
, "%s: read %ld bytes, expected %ld bytes\n",
328 context
, read_size
, (long) size
);
332 tfile_offset
= offset
+ size
;
337 /* Convert language code to string format. */
340 lang_to_string (lang
)
345 case langC
: return "C";
346 case langPascal
: return "Pascal";
347 case langFortran
: return "Fortran";
348 case langAssembler
: return "Assembler";
349 case langMachine
: return "Machine";
350 case langNil
: return "Nil";
351 case langAda
: return "Ada";
352 case langPl1
: return "Pl1";
353 case langCobol
: return "Cobol";
356 return "Unknown language";
360 /* Convert storage class to string. */
363 sc_to_string(storage_class
)
366 switch(storage_class
)
368 case sc_Nil
: return "Nil";
369 case sc_Text
: return "Text";
370 case sc_Data
: return "Data";
371 case sc_Bss
: return "Bss";
372 case sc_Register
: return "Register";
373 case sc_Abs
: return "Abs";
374 case sc_Undefined
: return "Undefined";
375 case sc_CdbLocal
: return "CdbLocal";
376 case sc_Bits
: return "Bits";
377 case sc_CdbSystem
: return "CdbSystem";
378 case sc_RegImage
: return "RegImage";
379 case sc_Info
: return "Info";
380 case sc_UserStruct
: return "UserStruct";
381 case sc_SData
: return "SData";
382 case sc_SBss
: return "SBss";
383 case sc_RData
: return "RData";
384 case sc_Var
: return "Var";
385 case sc_Common
: return "Common";
386 case sc_SCommon
: return "SCommon";
387 case sc_VarRegister
: return "VarRegister";
388 case sc_Variant
: return "Variant";
389 case sc_SUndefined
: return "SUndefined";
390 case sc_Init
: return "Init";
391 case sc_Max
: return "Max";
398 /* Convert symbol type to string. */
401 st_to_string(symbol_type
)
406 case st_Nil
: return "Nil";
407 case st_Global
: return "Global";
408 case st_Static
: return "Static";
409 case st_Param
: return "Param";
410 case st_Local
: return "Local";
411 case st_Label
: return "Label";
412 case st_Proc
: return "Proc";
413 case st_Block
: return "Block";
414 case st_End
: return "End";
415 case st_Member
: return "Member";
416 case st_Typedef
: return "Typedef";
417 case st_File
: return "File";
418 case st_RegReloc
: return "RegReloc";
419 case st_Forward
: return "Forward";
420 case st_StaticProc
: return "StaticProc";
421 case st_Constant
: return "Constant";
422 case st_StaParam
: return "StaticParam";
424 case st_Struct
: return "Struct";
425 case st_Union
: return "Union";
426 case st_Enum
: return "Enum";
428 case st_Str
: return "String";
429 case st_Number
: return "Number";
430 case st_Expr
: return "Expr";
431 case st_Type
: return "Type";
432 case st_Max
: return "Max";
439 /* Convert debug level to string. */
442 glevel_to_string (g_level
)
447 case GLEVEL_0
: return "G0";
448 case GLEVEL_1
: return "G1";
449 case GLEVEL_2
: return "G2";
450 case GLEVEL_3
: return "G3";
457 /* Convert the type information to string format. */
460 type_to_string (aux_ptr
, index
, fdp
)
475 static char buffer1
[1024];
476 static char buffer2
[1024];
479 char *used_ptr
= aux_used
+ (aux_ptr
- aux_symbols
);
481 for (i
= 0; i
< 7; i
++)
483 qualifiers
[i
].low_bound
= 0;
484 qualifiers
[i
].high_bound
= 0;
485 qualifiers
[i
].stride
= 0;
489 u
= aux_ptr
[index
++];
491 return "-1 (no type)";
493 basic_type
= (bt_t
) u
.ti
.bt
;
494 qualifiers
[0].type
= (tq_t
) u
.ti
.tq0
;
495 qualifiers
[1].type
= (tq_t
) u
.ti
.tq1
;
496 qualifiers
[2].type
= (tq_t
) u
.ti
.tq2
;
497 qualifiers
[3].type
= (tq_t
) u
.ti
.tq3
;
498 qualifiers
[4].type
= (tq_t
) u
.ti
.tq4
;
499 qualifiers
[5].type
= (tq_t
) u
.ti
.tq5
;
500 qualifiers
[6].type
= tq_Nil
;
503 * Go get the basic type.
507 case bt_Nil
: /* undefined */
511 case bt_Adr
: /* address - integer same size as pointer */
512 strcpy (p1
, "address");
515 case bt_Char
: /* character */
519 case bt_UChar
: /* unsigned character */
520 strcpy (p1
, "unsigned char");
523 case bt_Short
: /* short */
524 strcpy (p1
, "short");
527 case bt_UShort
: /* unsigned short */
528 strcpy (p1
, "unsigned short");
531 case bt_Int
: /* int */
535 case bt_UInt
: /* unsigned int */
536 strcpy (p1
, "unsigned int");
539 case bt_Long
: /* long */
543 case bt_ULong
: /* unsigned long */
544 strcpy (p1
, "unsigned long");
547 case bt_Float
: /* float (real) */
548 strcpy (p1
, "float");
551 case bt_Double
: /* Double (real) */
552 strcpy (p1
, "double");
555 /* Structures add 1-2 aux words:
556 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
557 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
559 case bt_Struct
: /* Structure (Record) */
560 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "struct", fdp
);
562 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
563 used_ptr
[++index
] = 1;
565 index
++; /* skip aux words */
568 /* Unions add 1-2 aux words:
569 1st word is [ST_RFDESCAPE, offset] pointer to union def;
570 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
572 case bt_Union
: /* Union */
573 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "union", fdp
);
575 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
576 used_ptr
[++index
] = 1;
578 index
++; /* skip aux words */
581 /* Enumerations add 1-2 aux words:
582 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
583 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
585 case bt_Enum
: /* Enumeration */
586 emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "enum", fdp
);
588 if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
589 used_ptr
[++index
] = 1;
591 index
++; /* skip aux words */
594 case bt_Typedef
: /* defined via a typedef, isymRef points */
595 strcpy (p1
, "typedef");
598 case bt_Range
: /* subrange of int */
599 strcpy (p1
, "subrange");
602 case bt_Set
: /* pascal sets */
606 case bt_Complex
: /* fortran complex */
607 strcpy (p1
, "complex");
610 case bt_DComplex
: /* fortran double complex */
611 strcpy (p1
, "double complex");
614 case bt_Indirect
: /* forward or unnamed typedef */
615 strcpy (p1
, "forward/unnamed typedef");
618 case bt_FixedDec
: /* Fixed Decimal */
619 strcpy (p1
, "fixed decimal");
622 case bt_FloatDec
: /* Float Decimal */
623 strcpy (p1
, "float decimal");
626 case bt_String
: /* Varying Length Character String */
627 strcpy (p1
, "string");
630 case bt_Bit
: /* Aligned Bit String */
634 case bt_Picture
: /* Picture */
635 strcpy (p1
, "picture");
638 case bt_Void
: /* Void */
643 sprintf (p1
, "Unknown basic type %d", (int) basic_type
);
647 p1
+= strlen (buffer1
);
650 * If this is a bitfield, get the bitsize.
657 bitsize
= aux_ptr
[index
++].width
;
658 sprintf (p1
, " : %d", bitsize
);
659 p1
+= strlen (buffer1
);
664 * Deal with any qualifiers.
666 if (qualifiers
[0].type
!= tq_Nil
)
669 * Snarf up any array bounds in the correct order. Arrays
670 * store 5 successive words in the aux. table:
671 * word 0 RNDXR to type of the bounds (ie, int)
672 * word 1 Current file descriptor index
674 * word 3 high bound (or -1 if [])
675 * word 4 stride size in bits
677 for (i
= 0; i
< 7; i
++)
679 if (qualifiers
[i
].type
== tq_Array
)
681 qualifiers
[i
].low_bound
= aux_ptr
[index
+2].dnLow
;
682 qualifiers
[i
].high_bound
= aux_ptr
[index
+3].dnHigh
;
683 qualifiers
[i
].stride
= aux_ptr
[index
+4].width
;
685 used_ptr
[index
+1] = 1;
686 used_ptr
[index
+2] = 1;
687 used_ptr
[index
+3] = 1;
688 used_ptr
[index
+4] = 1;
694 * Now print out the qualifiers.
696 for (i
= 0; i
< 6; i
++)
698 switch (qualifiers
[i
].type
)
705 strcpy (p2
, "ptr to ");
706 p2
+= sizeof ("ptr to ")-1;
710 strcpy (p2
, "volatile ");
711 p2
+= sizeof ("volatile ")-1;
716 p2
+= sizeof ("far ")-1;
720 strcpy (p2
, "func. ret. ");
721 p2
+= sizeof ("func. ret. ");
729 /* Print array bounds reversed (ie, in the order the C
730 programmer writes them). C is such a fun language.... */
732 while (i
< 5 && qualifiers
[i
+1].type
== tq_Array
)
735 for (j
= i
; j
>= first_array
; j
--)
737 strcpy (p2
, "array [");
738 p2
+= sizeof ("array [")-1;
739 if (qualifiers
[j
].low_bound
!= 0)
741 "%ld:%ld {%ld bits}",
742 (long) qualifiers
[j
].low_bound
,
743 (long) qualifiers
[j
].high_bound
,
744 (long) qualifiers
[j
].stride
);
746 else if (qualifiers
[j
].high_bound
!= -1)
749 (long) (qualifiers
[j
].high_bound
+ 1),
750 (long) (qualifiers
[j
].stride
));
753 sprintf (p2
, " {%ld bits}", (long) (qualifiers
[j
].stride
));
756 strcpy (p2
, "] of ");
757 p2
+= sizeof ("] of ")-1;
765 strcpy (p2
, buffer1
);
770 /* Print out the global file header for object files. */
773 print_global_hdr (ptr
)
776 char *time
= ctime ((time_t *)&ptr
->f_timdat
);
777 ushort flags
= ptr
->f_flags
;
779 printf("Global file header:\n");
780 printf(" %-*s 0x%x\n", 24, "magic number", (ushort
) ptr
->f_magic
);
781 printf(" %-*s %d\n", 24, "# sections", (int) ptr
->f_nscns
);
782 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr
->f_timdat
, time
);
783 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr
->f_symptr
);
784 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr
->f_nsyms
);
785 printf(" %-*s %ld\n", 24, "optional header", (long) ptr
->f_opthdr
);
786 printf(" %-*s 0x%x", 24, "flags", (ushort
) flags
);
788 if ((flags
& F_RELFLG
) != 0)
789 printf (", F_RELFLG");
791 if ((flags
& F_EXEC
) != 0)
794 if ((flags
& F_LNNO
) != 0)
797 if ((flags
& F_LSYMS
) != 0)
798 printf (", F_LSYMS");
800 if ((flags
& F_MINMAL
) != 0)
801 printf (", F_MINMAL");
803 if ((flags
& F_UPDATE
) != 0)
804 printf (", F_UPDATE");
806 if ((flags
& F_SWABD
) != 0)
807 printf (", F_SWABD");
809 if ((flags
& F_AR16WR
) != 0)
810 printf (", F_AR16WR");
812 if ((flags
& F_AR32WR
) != 0)
813 printf (", F_AR32WR");
815 if ((flags
& F_AR32W
) != 0)
816 printf (", F_AR32W");
818 if ((flags
& F_PATCH
) != 0)
819 printf (", F_PATCH/F_NODF");
825 /* Print out the symbolic header. */
828 print_sym_hdr (sym_ptr
)
833 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
834 sym_ptr
->magic
& 0xffff,
835 (sym_ptr
->vstamp
& 0xffff) >> 8,
836 sym_ptr
->vstamp
& 0xff);
838 printf(" %-*s %11s %11s %11s\n", width
, "Info", "Offset", "Number", "Bytes");
839 printf(" %-*s %11s %11s %11s\n", width
, "====", "======", "======", "=====\n");
841 printf(" %-*s %11ld %11ld %11ld [%d]\n", width
, "Line numbers",
842 (long) sym_ptr
->cbLineOffset
,
843 (long) sym_ptr
->cbLine
,
844 (long) sym_ptr
->cbLine
,
845 (int) sym_ptr
->ilineMax
);
847 printf(" %-*s %11ld %11ld %11ld\n", width
, "Dense numbers",
848 (long) sym_ptr
->cbDnOffset
,
849 (long) sym_ptr
->idnMax
,
850 (long) (sym_ptr
->idnMax
* sizeof (DNR
)));
852 printf(" %-*s %11ld %11ld %11ld\n", width
, "Procedures Tables",
853 (long) sym_ptr
->cbPdOffset
,
854 (long) sym_ptr
->ipdMax
,
855 (long) (sym_ptr
->ipdMax
* sizeof (PDR
)));
857 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Symbols",
858 (long) sym_ptr
->cbSymOffset
,
859 (long) sym_ptr
->isymMax
,
860 (long) (sym_ptr
->isymMax
* sizeof (SYMR
)));
862 printf(" %-*s %11ld %11ld %11ld\n", width
, "Optimization Symbols",
863 (long) sym_ptr
->cbOptOffset
,
864 (long) sym_ptr
->ioptMax
,
865 (long) (sym_ptr
->ioptMax
* sizeof (OPTR
)));
867 printf(" %-*s %11ld %11ld %11ld\n", width
, "Auxiliary Symbols",
868 (long) sym_ptr
->cbAuxOffset
,
869 (long) sym_ptr
->iauxMax
,
870 (long) (sym_ptr
->iauxMax
* sizeof (AUXU
)));
872 printf(" %-*s %11ld %11ld %11ld\n", width
, "Local Strings",
873 (long) sym_ptr
->cbSsOffset
,
874 (long) sym_ptr
->issMax
,
875 (long) sym_ptr
->issMax
);
877 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Strings",
878 (long) sym_ptr
->cbSsExtOffset
,
879 (long) sym_ptr
->issExtMax
,
880 (long) sym_ptr
->issExtMax
);
882 printf(" %-*s %11ld %11ld %11ld\n", width
, "File Tables",
883 (long) sym_ptr
->cbFdOffset
,
884 (long) sym_ptr
->ifdMax
,
885 (long) (sym_ptr
->ifdMax
* sizeof (FDR
)));
887 printf(" %-*s %11ld %11ld %11ld\n", width
, "Relative Files",
888 (long) sym_ptr
->cbRfdOffset
,
889 (long) sym_ptr
->crfd
,
890 (long) (sym_ptr
->crfd
* sizeof (ulong
)));
892 printf(" %-*s %11ld %11ld %11ld\n", width
, "External Symbols",
893 (long) sym_ptr
->cbExtOffset
,
894 (long) sym_ptr
->iextMax
,
895 (long) (sym_ptr
->iextMax
* sizeof (EXTR
)));
899 /* Print out a symbol. */
902 print_symbol (sym_ptr
, number
, strbase
, aux_base
, ifd
, fdp
)
910 sc_t storage_class
= (sc_t
) sym_ptr
->sc
;
911 st_t symbol_type
= (st_t
) sym_ptr
->st
;
912 ulong index
= sym_ptr
->index
;
913 char *used_ptr
= aux_used
+ (aux_base
- aux_symbols
);
916 printf ("\n Symbol# %d: \"%s\"\n", number
, sym_ptr
->iss
+ strbase
);
918 if (aux_base
!= (AUXU
*) 0 && index
!= indexNil
)
927 printf (" End+1 symbol: %ld\n", index
);
930 if (free_scope
== (scope_t
*) 0)
931 scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
934 scope_ptr
= free_scope
;
935 free_scope
= scope_ptr
->prev
;
937 scope_ptr
->open_sym
= number
;
938 scope_ptr
->st
= symbol_type
;
939 scope_ptr
->sc
= storage_class
;
940 scope_ptr
->prev
= cur_scope
;
941 cur_scope
= scope_ptr
;
946 if (storage_class
== sc_Text
|| storage_class
== sc_Info
)
947 printf (" First symbol: %ld\n", index
);
951 printf (" First symbol: %ld\n", (long) aux_base
[index
].isym
);
956 if (cur_scope
== (scope_t
*) 0)
957 printf (" Can't pop end scope\n");
960 scope_ptr
= cur_scope
;
961 cur_scope
= scope_ptr
->prev
;
962 scope_ptr
->prev
= free_scope
;
963 free_scope
= scope_ptr
;
970 if (MIPS_IS_STAB(sym_ptr
))
972 else if (ifd
== -1) /* local symbol */
974 used_ptr
[index
] = used_ptr
[index
+1] = 1;
975 printf (" End+1 symbol: %-7ld Type: %s\n",
976 (long) aux_base
[index
].isym
,
977 type_to_string (aux_base
, index
+1, fdp
));
979 else /* global symbol */
980 printf (" Local symbol: %ld\n", index
);
984 if (free_scope
== (scope_t
*) 0)
985 scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
988 scope_ptr
= free_scope
;
989 free_scope
= scope_ptr
->prev
;
991 scope_ptr
->open_sym
= number
;
992 scope_ptr
->st
= symbol_type
;
993 scope_ptr
->sc
= storage_class
;
994 scope_ptr
->prev
= cur_scope
;
995 cur_scope
= scope_ptr
;
1003 printf (" End+1 symbol: %lu\n", index
);
1008 if (!MIPS_IS_STAB (sym_ptr
))
1010 used_ptr
[index
] = 1;
1011 printf (" Type: %s\n",
1012 type_to_string (aux_base
, index
, fdp
));
1019 printf (" Scopes: ");
1020 if (cur_scope
== (scope_t
*) 0)
1024 for (scope_ptr
= cur_scope
;
1025 scope_ptr
!= (scope_t
*) 0;
1026 scope_ptr
= scope_ptr
->prev
)
1029 if (scope_ptr
->st
== st_Proc
|| scope_ptr
->st
== st_StaticProc
)
1031 else if (scope_ptr
->st
== st_File
)
1033 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Text
)
1035 else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Info
)
1040 printf (" %ld [%s]", scope_ptr
->open_sym
, class);
1046 printf (" Value: %-13ld ",
1047 (long)sym_ptr
->value
);
1049 printf ("String index: %ld\n", (long)sym_ptr
->iss
);
1051 printf ("String index: %-11ld Ifd: %d\n",
1052 (long)sym_ptr
->iss
, ifd
);
1054 printf (" Symbol type: %-11sStorage class: %-11s",
1055 st_to_string (symbol_type
), sc_to_string (storage_class
));
1057 if (MIPS_IS_STAB(sym_ptr
))
1059 register int i
= sizeof(stab_names
) / sizeof(stab_names
[0]);
1060 const char *stab_name
= "stab";
1061 short code
= MIPS_UNMARK_STAB(sym_ptr
->index
);
1063 if (stab_names
[i
].code
== code
)
1065 stab_name
= stab_names
[i
].string
;
1068 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr
->index
, stab_name
);
1070 else if (sym_ptr
->st
== stLabel
&& sym_ptr
->index
!= indexNil
)
1071 printf ("Index: %ld (line#)\n", (long)sym_ptr
->index
);
1073 printf ("Index: %ld\n", (long)sym_ptr
->index
);
1078 /* Print out a word from the aux. table in various formats. */
1081 print_aux (u
, auxi
, used
)
1086 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1087 (used
) ? " " : "* ",
1091 (long) u
.rndx
.index
,
1104 /* Write aggregate information to a string. */
1107 emit_aggregate (string
, u
, u2
, which
, fdp
)
1114 unsigned int ifd
= u
.rndx
.rfd
;
1115 unsigned int index
= u
.rndx
.index
;
1118 if (ifd
== ST_RFDESCAPE
)
1121 /* An ifd of -1 is an opaque type. An escaped index of 0 is a
1122 struct return type of a procedure compiled without -g. */
1123 if (ifd
== 0xffffffff
1124 || (u
.rndx
.rfd
== ST_RFDESCAPE
&& index
== 0))
1125 name
= "<undefined>";
1126 else if (index
== indexNil
)
1130 if (fdp
== 0 || sym_hdr
.crfd
== 0)
1131 fdp
= &file_desc
[ifd
];
1133 fdp
= &file_desc
[rfile_desc
[fdp
->rfdBase
+ ifd
]];
1134 name
= &l_strings
[fdp
->issBase
+ l_symbols
[index
+ fdp
->isymBase
].iss
];
1138 "%s %s { ifd = %u, index = %u }",
1139 which
, name
, ifd
, index
);
1143 /* Print out information about a file descriptor, and the symbols,
1144 procedures, and line numbers within it. */
1147 print_file_desc (fdp
, number
)
1157 str_base
= l_strings
+ fdp
->issBase
;
1158 aux_base
= aux_symbols
+ fdp
->iauxBase
;
1159 used_base
= aux_used
+ (aux_base
- aux_symbols
);
1161 printf ("\nFile #%d, \"%s\"\n\n",
1163 fdp
->rss
!= issNil
? str_base
+ fdp
->rss
: "<unknown>");
1165 printf (" Name index = %-10ld Readin = %s\n",
1166 (long) fdp
->rss
, (fdp
->fReadin
) ? "Yes" : "No");
1168 printf (" Merge = %-10s Endian = %s\n",
1169 (fdp
->fMerge
) ? "Yes" : "No",
1170 (fdp
->fBigendian
) ? "BIG" : "LITTLE");
1172 printf (" Debug level = %-10s Language = %s\n",
1173 glevel_to_string (fdp
->glevel
),
1174 lang_to_string((lang_t
) fdp
->lang
));
1176 printf (" Adr = 0x%08lx\n\n", (long) fdp
->adr
);
1178 printf(" %-*s %11s %11s %11s %11s\n", width
, "Info", "Start", "Number", "Size", "Offset");
1179 printf(" %-*s %11s %11s %11s %11s\n", width
, "====", "=====", "======", "====", "======");
1181 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1182 width
, "Local strings",
1183 (ulong
) fdp
->issBase
,
1186 (ulong
) (fdp
->issBase
+ sym_hdr
.cbSsOffset
));
1188 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1189 width
, "Local symbols",
1190 (ulong
) fdp
->isymBase
,
1192 (ulong
) (fdp
->csym
* sizeof (SYMR
)),
1193 (ulong
) (fdp
->isymBase
* sizeof (SYMR
) + sym_hdr
.cbSymOffset
));
1195 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1196 width
, "Line numbers",
1197 (ulong
) fdp
->cbLineOffset
,
1199 (ulong
) fdp
->cbLine
,
1200 (ulong
) (fdp
->cbLineOffset
+ sym_hdr
.cbLineOffset
));
1202 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1203 width
, "Optimization symbols",
1204 (ulong
) fdp
->ioptBase
,
1206 (ulong
) (fdp
->copt
* sizeof (OPTR
)),
1207 (ulong
) (fdp
->ioptBase
* sizeof (OPTR
) + sym_hdr
.cbOptOffset
));
1209 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1210 width
, "Procedures",
1211 (ulong
) fdp
->ipdFirst
,
1213 (ulong
) (fdp
->cpd
* sizeof (PDR
)),
1214 (ulong
) (fdp
->ipdFirst
* sizeof (PDR
) + sym_hdr
.cbPdOffset
));
1216 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1217 width
, "Auxiliary symbols",
1218 (ulong
) fdp
->iauxBase
,
1220 (ulong
) (fdp
->caux
* sizeof (AUXU
)),
1221 (ulong
) (fdp
->iauxBase
* sizeof(AUXU
) + sym_hdr
.cbAuxOffset
));
1223 printf(" %-*s %11lu %11lu %11lu %11lu\n",
1224 width
, "Relative Files",
1225 (ulong
) fdp
->rfdBase
,
1227 (ulong
) (fdp
->crfd
* sizeof (ulong
)),
1228 (ulong
) (fdp
->rfdBase
* sizeof(ulong
) + sym_hdr
.cbRfdOffset
));
1231 if (want_scope
&& cur_scope
!= (scope_t
*) 0)
1232 printf ("\n Warning scope does not start at 0!\n");
1235 * print the info about the symbol table.
1237 printf ("\n There are %lu local symbols, starting at %lu\n",
1239 (ulong
) (fdp
->isymBase
+ sym_hdr
.cbSymOffset
));
1241 for(symi
= fdp
->isymBase
; symi
< (fdp
->csym
+ fdp
->isymBase
); symi
++)
1242 print_symbol (&l_symbols
[symi
],
1243 symi
- fdp
->isymBase
,
1249 if (want_scope
&& cur_scope
!= (scope_t
*) 0)
1250 printf ("\n Warning scope does not end at 0!\n");
1253 * print the aux. table if desired.
1256 if (want_aux
&& fdp
->caux
!= 0)
1260 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
1262 (ulong
) (fdp
->iauxBase
+ sym_hdr
.cbAuxOffset
));
1264 for (auxi
= fdp
->iauxBase
; auxi
< (fdp
->caux
+ fdp
->iauxBase
); auxi
++)
1265 print_aux (aux_base
[auxi
], auxi
, used_base
[auxi
]);
1269 * print the relative file descriptors.
1271 if (want_rfd
&& fdp
->crfd
!= 0)
1275 printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
1277 (ulong
) fdp
->rfdBase
);
1279 rfd_ptr
= rfile_desc
+ fdp
->rfdBase
;
1280 for (i
= 0; i
< (ulong
) fdp
->crfd
; i
++)
1282 printf ("\t#%-5ld %11ld, 0x%08lx\n", i
, *rfd_ptr
, *rfd_ptr
);
1288 * do the procedure descriptors.
1290 printf ("\n There are %lu procedure descriptor entries, ", (ulong
) fdp
->cpd
);
1291 printf ("starting at %lu.\n", (ulong
) fdp
->ipdFirst
);
1293 for (pdi
= fdp
->ipdFirst
; pdi
< (fdp
->cpd
+ fdp
->ipdFirst
); pdi
++)
1295 PDR
*proc_ptr
= &proc_desc
[pdi
];
1296 printf ("\n\tProcedure descriptor %d:\n", (pdi
- fdp
->ipdFirst
));
1299 printf ("\t Name index = %-11ld Name = \"%s\"\n",
1300 (long) l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
,
1301 l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
+ str_base
);
1303 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1304 (long) proc_ptr
->regmask
,
1305 (long) proc_ptr
->regoffset
,
1306 (long) proc_ptr
->fregmask
,
1307 (long) proc_ptr
->fregoffset
);
1309 printf ("\t .frame $%d,%ld,$%d\n",
1310 (int) proc_ptr
->framereg
,
1311 (long) proc_ptr
->frameoffset
,
1312 (int) proc_ptr
->pcreg
);
1314 printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
1315 (long) proc_ptr
->iopt
,
1316 (long) proc_ptr
->isym
);
1318 printf ("\t First line # = %-11ld Last line # = %ld\n",
1319 (long) proc_ptr
->lnLow
,
1320 (long) proc_ptr
->lnHigh
);
1322 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
1323 (long) proc_ptr
->cbLineOffset
,
1324 (long) proc_ptr
->adr
);
1327 * print the line number entries.
1330 if (want_line
&& fdp
->cline
!= 0)
1333 long cur_line
= proc_ptr
->lnLow
;
1334 uchar
*line_ptr
= (((uchar
*)lines
) + proc_ptr
->cbLineOffset
1335 + fdp
->cbLineOffset
);
1338 if (pdi
== fdp
->cpd
+ fdp
->ipdFirst
- 1) /* last procedure */
1339 line_end
= ((uchar
*)lines
) + fdp
->cbLine
+ fdp
->cbLineOffset
;
1340 else /* not last proc. */
1341 line_end
= (((uchar
*)lines
) + proc_desc
[pdi
+1].cbLineOffset
1342 + fdp
->cbLineOffset
);
1344 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1345 (ulong
) (line_end
- line_ptr
),
1346 (ulong
) (fdp
->ilineBase
+ sym_hdr
.cbLineOffset
));
1348 while (line_ptr
< line_end
)
1349 { /* sign extend nibble */
1350 delta
= ((*line_ptr
>> 4) ^ 0x8) - 0x8;
1351 count
= (*line_ptr
& 0xf) + 1;
1356 delta
= (((line_ptr
[1]) & 0xff) << 8) + ((line_ptr
[2]) & 0xff);
1357 delta
= (delta
^ 0x8000) - 0x8000;
1362 printf ("\t Line %11ld, delta %5d, count %2d\n",
1372 /* Read in the portions of the .T file that we will print out. */
1375 read_tfile
__proto((void))
1378 off_t sym_hdr_offset
= 0;
1380 (void) read_seek ((PTR_T
) &magic
, sizeof (magic
), (off_t
) 0, "Magic number");
1383 /* Print out the global header, since this is not a T-file. */
1385 (void) read_seek ((PTR_T
) &global_hdr
, sizeof (global_hdr
), (off_t
) 0,
1386 "Global file header");
1388 print_global_hdr (&global_hdr
);
1390 if (global_hdr
.f_symptr
== 0)
1392 printf ("No symbolic header, Goodbye!\n");
1396 sym_hdr_offset
= global_hdr
.f_symptr
;
1399 (void) read_seek ((PTR_T
) &sym_hdr
,
1404 print_sym_hdr (&sym_hdr
);
1406 lines
= (LINER
*) read_seek ((PTR_T
) 0,
1408 sym_hdr
.cbLineOffset
,
1411 dense_nums
= (DNR
*) read_seek ((PTR_T
) 0,
1412 sym_hdr
.idnMax
* sizeof (DNR
),
1416 proc_desc
= (PDR
*) read_seek ((PTR_T
) 0,
1417 sym_hdr
.ipdMax
* sizeof (PDR
),
1419 "Procedure tables");
1421 l_symbols
= (SYMR
*) read_seek ((PTR_T
) 0,
1422 sym_hdr
.isymMax
* sizeof (SYMR
),
1423 sym_hdr
.cbSymOffset
,
1426 opt_symbols
= (OPTR
*) read_seek ((PTR_T
) 0,
1427 sym_hdr
.ioptMax
* sizeof (OPTR
),
1428 sym_hdr
.cbOptOffset
,
1429 "Optimization symbols");
1431 aux_symbols
= (AUXU
*) read_seek ((PTR_T
) 0,
1432 sym_hdr
.iauxMax
* sizeof (AUXU
),
1433 sym_hdr
.cbAuxOffset
,
1434 "Auxiliary symbols");
1436 if (sym_hdr
.iauxMax
> 0)
1438 aux_used
= calloc (sym_hdr
.iauxMax
, 1);
1439 if (aux_used
== (char *) 0)
1446 l_strings
= (char *) read_seek ((PTR_T
) 0,
1449 "Local string table");
1451 e_strings
= (char *) read_seek ((PTR_T
) 0,
1453 sym_hdr
.cbSsExtOffset
,
1454 "External string table");
1456 file_desc
= (FDR
*) read_seek ((PTR_T
) 0,
1457 sym_hdr
.ifdMax
* sizeof (FDR
),
1461 rfile_desc
= (ulong
*) read_seek ((PTR_T
) 0,
1462 sym_hdr
.crfd
* sizeof (ulong
),
1463 sym_hdr
.cbRfdOffset
,
1464 "Relative file tables");
1466 e_symbols
= (EXTR
*) read_seek ((PTR_T
) 0,
1467 sym_hdr
.iextMax
* sizeof (EXTR
),
1468 sym_hdr
.cbExtOffset
,
1469 "External symbols");
1484 while ((opt
= getopt (argc
, argv
, "alrst")) != EOF
)
1487 default: errors
++; break;
1488 case 'a': want_aux
++; break; /* print aux table */
1489 case 'l': want_line
++; break; /* print line numbers */
1490 case 'r': want_rfd
++; break; /* print relative fd's */
1491 case 's': want_scope
++; break; /* print scope info */
1492 case 't': tfile
++; break; /* this is a tfile (without header), and not a .o */
1495 if (errors
|| optind
!= argc
- 1)
1497 fprintf (stderr
, "Calling Sequence:\n");
1498 fprintf (stderr
, "\t%s [-alrst] <object-or-T-file>\n", argv
[0]);
1499 fprintf (stderr
, "\n");
1500 fprintf (stderr
, "switches:\n");
1501 fprintf (stderr
, "\t-a Print out auxiliary table.\n");
1502 fprintf (stderr
, "\t-l Print out line numbers.\n");
1503 fprintf (stderr
, "\t-r Print out relative file descriptors.\n");
1504 fprintf (stderr
, "\t-s Print out the current scopes for an item.\n");
1505 fprintf (stderr
, "\t-t Assume there is no global header (ie, a T-file).\n");
1510 * Open and process the input file.
1512 tfile_fd
= open (argv
[optind
], O_RDONLY
);
1515 perror (argv
[optind
]);
1522 * Print any global aux words if any.
1526 long last_aux_in_use
;
1528 if (sym_hdr
.ifdMax
!= 0 && file_desc
[0].iauxBase
!= 0)
1530 printf ("\nGlobal auxiliary entries before first file:\n");
1531 for (i
= 0; i
< file_desc
[0].iauxBase
; i
++)
1532 print_aux (aux_symbols
[i
], 0, aux_used
[i
]);
1535 if (sym_hdr
.ifdMax
== 0)
1536 last_aux_in_use
= 0;
1539 = (file_desc
[sym_hdr
.ifdMax
-1].iauxBase
1540 + file_desc
[sym_hdr
.ifdMax
-1].caux
- 1);
1542 if (last_aux_in_use
< sym_hdr
.iauxMax
-1)
1544 printf ("\nGlobal auxiliary entries after last file:\n");
1545 for (i
= last_aux_in_use
; i
< sym_hdr
.iauxMax
; i
++)
1546 print_aux (aux_symbols
[i
], i
- last_aux_in_use
, aux_used
[i
]);
1551 * Print the information for each file.
1553 for (i
= 0; i
< sym_hdr
.ifdMax
; i
++)
1554 print_file_desc (&file_desc
[i
], i
);
1557 * Print the external symbols.
1559 want_scope
= 0; /* scope info is meaning for extern symbols */
1560 printf ("\nThere are %lu external symbols, starting at %lu\n",
1561 (ulong
) sym_hdr
.iextMax
,
1562 (ulong
) sym_hdr
.cbExtOffset
);
1564 for(i
= 0; i
< sym_hdr
.iextMax
; i
++)
1565 print_symbol (&e_symbols
[i
].asym
, i
, e_strings
,
1566 aux_symbols
+ file_desc
[e_symbols
[i
].ifd
].iauxBase
,
1568 &file_desc
[e_symbols
[i
].ifd
]);
1571 * Print unused aux symbols now.
1578 for (i
= 0; i
< sym_hdr
.iauxMax
; i
++)
1584 printf ("\nThe following auxiliary table entries were unused:\n\n");
1588 printf (" #%-5d %11ld 0x%08lx %s\n",
1590 (long) aux_symbols
[i
].isym
,
1591 (long) aux_symbols
[i
].isym
,
1592 type_to_string (aux_symbols
, i
, (FDR
*) 0));
1604 fprintf (stderr
, "mips-tdump internal error");