/* Read and manage MIPS symbol tables from object modules.
Source originally from hartzell@boulder.colorado.edu
Rewritten by: meissner@osf.org
Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ST_RFDESCAPE 0xfff
typedef const void *CPTR_T
;
#if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
typedef char *PTR_T
; /* Ultrix 3.1 */
#define uchar unsigned char
#define ushort unsigned short
#define uint unsigned int
#define ulong unsigned long
/* Do to size_t being defined in sys/types.h and different
in stddef.h, we have to do this by hand..... Note, these
types are correct for MIPS based systems, and may not be
correct for other systems. */
/* Redefinition of of storage classes as an enumeration for better
#define stStaParam 16 /* Fortran static parameters */
#define btVoid 26 /* void basic type */
sc_Nil
= scNil
, /* no storage class */
sc_Text
= scText
, /* text symbol */
sc_Data
= scData
, /* initialized data symbol */
sc_Bss
= scBss
, /* un-initialized data symbol */
sc_Register
= scRegister
, /* value of symbol is register number */
sc_Abs
= scAbs
, /* value of symbol is absolute */
sc_Undefined
= scUndefined
, /* who knows? */
sc_CdbLocal
= scCdbLocal
, /* variable's value is IN se->va.?? */
sc_Bits
= scBits
, /* this is a bit field */
sc_CdbSystem
= scCdbSystem
, /* var's value is IN CDB's address space */
sc_RegImage
= scRegImage
, /* register value saved on stack */
sc_Info
= scInfo
, /* symbol contains debugger information */
sc_UserStruct
= scUserStruct
, /* addr in struct user for current process */
sc_SData
= scSData
, /* load time only small data */
sc_SBss
= scSBss
, /* load time only small common */
sc_RData
= scRData
, /* load time only read only data */
sc_Var
= scVar
, /* Var parameter (fortran,pascal) */
sc_Common
= scCommon
, /* common variable */
sc_SCommon
= scSCommon
, /* small common */
sc_VarRegister
= scVarRegister
, /* Var parameter in a register */
sc_Variant
= scVariant
, /* Variant record */
sc_SUndefined
= scSUndefined
, /* small undefined(external) data */
sc_Init
= scInit
, /* .init section symbol */
sc_Max
= scMax
/* Max storage class+1 */
/* Redefinition of symbol type. */
st_Nil
= stNil
, /* Nuthin' special */
st_Global
= stGlobal
, /* external symbol */
st_Static
= stStatic
, /* static */
st_Param
= stParam
, /* procedure argument */
st_Local
= stLocal
, /* local variable */
st_Label
= stLabel
, /* label */
st_Proc
= stProc
, /* " " Procedure */
st_Block
= stBlock
, /* beginning of block */
st_End
= stEnd
, /* end (of anything) */
st_Member
= stMember
, /* member (of anything - struct/union/enum */
st_Typedef
= stTypedef
, /* type definition */
st_File
= stFile
, /* file name */
st_RegReloc
= stRegReloc
, /* register relocation */
st_Forward
= stForward
, /* forwarding address */
st_StaticProc
= stStaticProc
, /* load time only static procs */
st_StaParam
= stStaParam
, /* Fortran static parameters */
st_Constant
= stConstant
, /* const */
st_Str
= stStr
, /* string */
st_Number
= stNumber
, /* pure number (ie. 4 NOR 2+2) */
st_Expr
= stExpr
, /* 2+2 vs. 4 */
st_Type
= stType
, /* post-coercion SER */
st_Max
= stMax
/* max type+1 */
/* Redefinition of type qualifiers. */
tq_Nil
= tqNil
, /* bt is what you see */
tq_Ptr
= tqPtr
, /* pointer */
tq_Proc
= tqProc
, /* procedure */
tq_Array
= tqArray
, /* duh */
tq_Far
= tqFar
, /* longer addressing - 8086/8 land */
tq_Vol
= tqVol
, /* volatile */
tq_Max
= tqMax
/* Max type qualifier+1 */
/* Redefinition of basic types. */
bt_Nil
= btNil
, /* undefined */
bt_Adr
= btAdr
, /* address - integer same size as pointer */
bt_Char
= btChar
, /* character */
bt_UChar
= btUChar
, /* unsigned character */
bt_Short
= btShort
, /* short */
bt_UShort
= btUShort
, /* unsigned short */
bt_Int
= btInt
, /* int */
bt_UInt
= btUInt
, /* unsigned int */
bt_Long
= btLong
, /* long */
bt_ULong
= btULong
, /* unsigned long */
bt_Float
= btFloat
, /* float (real) */
bt_Double
= btDouble
, /* Double (real) */
bt_Struct
= btStruct
, /* Structure (Record) */
bt_Union
= btUnion
, /* Union (variant) */
bt_Enum
= btEnum
, /* Enumerated */
bt_Typedef
= btTypedef
, /* defined via a typedef, isymRef points */
bt_Range
= btRange
, /* subrange of int */
bt_Set
= btSet
, /* pascal sets */
bt_Complex
= btComplex
, /* fortran complex */
bt_DComplex
= btDComplex
, /* fortran double complex */
bt_Indirect
= btIndirect
, /* forward or unnamed typedef */
bt_FixedDec
= btFixedDec
, /* Fixed Decimal */
bt_FloatDec
= btFloatDec
, /* Float Decimal */
bt_String
= btString
, /* Varying Length Character String */
bt_Bit
= btBit
, /* Aligned Bit String */
bt_Picture
= btPicture
, /* Picture */
bt_Void
= btVoid
, /* void */
bt_Max
= btMax
/* Max basic type+1 */
/* Redefinition of the language codes. */
lang_Pascal
= langPascal
,
lang_Fortran
= langFortran
,
lang_Assembler
= langAssembler
,
lang_Machine
= langMachine
,
/* Redefinition of the debug level codes. */
/* Keep track of the active scopes. */
struct scope
*prev
; /* previous scope */
ulong open_sym
; /* symbol opening scope */
sc_t sc
; /* storage class */
st_t st
; /* symbol type */
struct filehdr global_hdr
; /* a.out header */
int errors
= 0; /* # of errors */
int want_aux
= 0; /* print aux table */
int want_line
= 0; /* print line numbers */
int want_rfd
= 0; /* print relative file desc's */
int want_scope
= 0; /* print scopes for every symbol */
int tfile_fd
; /* file descriptor of .T file */
off_t tfile_offset
; /* current offset in .T file */
scope_t
*cur_scope
= 0; /* list of active scopes */
scope_t
*free_scope
= 0; /* list of freed scopes */
HDRR sym_hdr
; /* symbolic header */
char *l_strings
; /* local strings */
char *e_strings
; /* external strings */
SYMR
*l_symbols
; /* local symbols */
EXTR
*e_symbols
; /* external symbols */
LINER
*lines
; /* line numbers */
DNR
*dense_nums
; /* dense numbers */
OPTR
*opt_symbols
; /* optimization symbols */
AUXU
*aux_symbols
; /* Auxiliary symbols */
char *aux_used
; /* map of which aux syms are used */
FDR
*file_desc
; /* file tables */
ulong
*rfile_desc
; /* relative file tables */
PDR
*proc_desc
; /* procedure tables */
/* Forward reference for functions. */
PTR_T read_seek
__proto((PTR_T
, size_t, off_t
, const char *));
void read_tfile
__proto((void));
void print_global_hdr
__proto((struct filehdr
*));
void print_sym_hdr
__proto((HDRR
*));
void print_file_desc
__proto((FDR
*, int));
void print_symbol
__proto((SYMR
*, int, char *, AUXU
*, int));
void print_aux
__proto((AUXU
, int, int));
void emit_aggregate
__proto((char *, AUXU
, AUXU
, const char *));
char *st_to_string
__proto((st_t
));
char *sc_to_string
__proto((sc_t
));
char *glevel_to_string
__proto((glevel_t
));
char *lang_to_string
__proto((lang_t
));
char *type_to_string
__proto((AUXU
*, int));
extern PTR_T malloc
__proto((size_t));
extern PTR_T calloc
__proto((size_t, size_t));
extern PTR_T realloc
__proto((PTR_T
, size_t));
extern void free
__proto((PTR_T
));
extern char *ctime
__proto((time_t *));
/* Create a table of debugging stab-codes and corresponding names. */
#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
struct {short code
; char string
[10];} stab_names
[] = {
/* Read some bytes at a specified location, and return a pointer. */
read_seek (ptr
, size
, offset
, context
)
PTR_T ptr
; /* pointer to buffer or NULL */
size_t size
; /* # bytes to read */
off_t offset
; /* offset to read at */
const char *context
; /* context for error message */
if (size
== 0) /* nothing to read */
if ((ptr
== (PTR_T
)0 && (ptr
= malloc (size
)) == (PTR_T
)0)
|| (tfile_offset
!= offset
&& lseek (tfile_fd
, offset
, 0) == -1)
|| (read_size
= read (tfile_fd
, ptr
, size
)) < 0)
fprintf (stderr
, "%s: read %ld bytes, expected %ld bytes\n",
context
, read_size
, (long) size
);
tfile_offset
= offset
+ size
;
/* Convert language code to string format. */
case langPascal
: return "Pascal";
case langFortran
: return "Fortran";
case langAssembler
: return "Assembler";
case langMachine
: return "Machine";
case langNil
: return "Nil";
case langAda
: return "Ada";
case langPl1
: return "Pl1";
case langCobol
: return "Cobol";
return "Unknown language";
/* Convert storage class to string. */
sc_to_string(storage_class
)
case sc_Nil
: return "Nil";
case sc_Text
: return "Text";
case sc_Data
: return "Data";
case sc_Bss
: return "Bss";
case sc_Register
: return "Register";
case sc_Abs
: return "Abs";
case sc_Undefined
: return "Undefined";
case sc_CdbLocal
: return "CdbLocal";
case sc_Bits
: return "Bits";
case sc_CdbSystem
: return "CdbSystem";
case sc_RegImage
: return "RegImage";
case sc_Info
: return "Info";
case sc_UserStruct
: return "UserStruct";
case sc_SData
: return "SData";
case sc_SBss
: return "SBss";
case sc_RData
: return "RData";
case sc_Var
: return "Var";
case sc_Common
: return "Common";
case sc_SCommon
: return "SCommon";
case sc_VarRegister
: return "VarRegister";
case sc_Variant
: return "Variant";
case sc_SUndefined
: return "SUndefined";
case sc_Init
: return "Init";
case sc_Max
: return "Max";
/* Convert symbol type to string. */
st_to_string(symbol_type
)
case st_Nil
: return "Nil";
case st_Global
: return "Global";
case st_Static
: return "Static";
case st_Param
: return "Param";
case st_Local
: return "Local";
case st_Label
: return "Label";
case st_Proc
: return "Proc";
case st_Block
: return "Block";
case st_End
: return "End";
case st_Member
: return "Member";
case st_Typedef
: return "Typedef";
case st_File
: return "File";
case st_RegReloc
: return "RegReloc";
case st_Forward
: return "Forward";
case st_StaticProc
: return "StaticProc";
case st_Constant
: return "Constant";
case st_StaParam
: return "StaticParam";
case st_Str
: return "String";
case st_Number
: return "Number";
case st_Expr
: return "Expr";
case st_Type
: return "Type";
case st_Max
: return "Max";
/* Convert debug level to string. */
glevel_to_string (g_level
)
case GLEVEL_0
: return "G0";
case GLEVEL_1
: return "G1";
case GLEVEL_2
: return "G2";
case GLEVEL_3
: return "G3";
/* Convert the type information to string format. */
type_to_string (aux_ptr
, index
)
static char buffer1
[1024];
static char buffer2
[1024];
char *used_ptr
= aux_used
+ (aux_ptr
- aux_symbols
);
qualifiers
[i
].low_bound
= 0;
qualifiers
[i
].high_bound
= 0;
qualifiers
[i
].stride
= 0;
basic_type
= (bt_t
) u
.ti
.bt
;
qualifiers
[0].type
= (tq_t
) u
.ti
.tq0
;
qualifiers
[1].type
= (tq_t
) u
.ti
.tq1
;
qualifiers
[2].type
= (tq_t
) u
.ti
.tq2
;
qualifiers
[3].type
= (tq_t
) u
.ti
.tq3
;
qualifiers
[4].type
= (tq_t
) u
.ti
.tq4
;
qualifiers
[5].type
= (tq_t
) u
.ti
.tq5
;
qualifiers
[6].type
= tq_Nil
;
case bt_Nil
: /* undefined */
case bt_Adr
: /* address - integer same size as pointer */
case bt_Char
: /* character */
case bt_UChar
: /* unsigned character */
strcpy (p1
, "unsigned char");
case bt_Short
: /* short */
case bt_UShort
: /* unsigned short */
strcpy (p1
, "unsigned short");
case bt_UInt
: /* unsigned int */
strcpy (p1
, "unsigned int");
case bt_ULong
: /* unsigned long */
strcpy (p1
, "unsigned long");
case bt_Float
: /* float (real) */
case bt_Double
: /* Double (real) */
/* Structures add 1-2 aux words:
1st word is [ST_RFDESCAPE, offset] pointer to struct def;
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case bt_Struct
: /* Structure (Record) */
emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "struct");
if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
index
++; /* skip aux words */
/* Unions add 1-2 aux words:
1st word is [ST_RFDESCAPE, offset] pointer to union def;
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case bt_Union
: /* Union */
emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "union");
if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
index
++; /* skip aux words */
/* Enumerations add 1-2 aux words:
1st word is [ST_RFDESCAPE, offset] pointer to enum def;
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case bt_Enum
: /* Enumeration */
emit_aggregate (p1
, aux_ptr
[index
], aux_ptr
[index
+1], "enum");
if (aux_ptr
[index
].rndx
.rfd
== ST_RFDESCAPE
)
index
++; /* skip aux words */
case bt_Typedef
: /* defined via a typedef, isymRef points */
case bt_Range
: /* subrange of int */
case bt_Set
: /* pascal sets */
case bt_Complex
: /* fortran complex */
case bt_DComplex
: /* fortran double complex */
strcpy (p1
, "double complex");
case bt_Indirect
: /* forward or unnamed typedef */
strcpy (p1
, "forward/unamed typedef");
case bt_FixedDec
: /* Fixed Decimal */
strcpy (p1
, "fixed decimal");
case bt_FloatDec
: /* Float Decimal */
strcpy (p1
, "float decimal");
case bt_String
: /* Varying Length Character String */
case bt_Bit
: /* Aligned Bit String */
case bt_Picture
: /* Picture */
sprintf (p1
, "Unknown basic type %d", (int) basic_type
);
* If this is a bitfield, get the bitsize.
bitsize
= aux_ptr
[index
++].width
;
sprintf (p1
, " : %d", bitsize
);
* Deal with any qualifiers.
if (qualifiers
[0].type
!= tq_Nil
)
* Snarf up any array bounds in the correct order. Arrays
* store 5 successive words in the aux. table:
* word 0 RNDXR to type of the bounds (ie, int)
* word 1 Current file descriptor index
* word 3 high bound (or -1 if [])
* word 4 stride size in bits
if (qualifiers
[i
].type
== tq_Array
)
qualifiers
[i
].low_bound
= aux_ptr
[index
+2].dnLow
;
qualifiers
[i
].high_bound
= aux_ptr
[index
+3].dnHigh
;
qualifiers
[i
].stride
= aux_ptr
[index
+4].width
;
* Now print out the qualifiers.
switch (qualifiers
[i
].type
)
p2
+= sizeof ("ptr to ")-1;
strcpy (p2
, "volatile ");
p2
+= sizeof ("volatile ")-1;
strcpy (p2
, "func. ret. ");
p2
+= sizeof ("func. ret. ");
/* Print array bounds reversed (ie, in the order the C
programmer writes them). C is such a fun language.... */
while (i
< 5 && qualifiers
[i
+1].type
== tq_Array
)
for (j
= i
; j
>= first_array
; j
--)
p2
+= sizeof ("array [")-1;
if (qualifiers
[j
].low_bound
!= 0)
(long) qualifiers
[j
].low_bound
,
(long) qualifiers
[j
].high_bound
,
(long) qualifiers
[j
].stride
);
else if (qualifiers
[j
].high_bound
!= -1)
(long) (qualifiers
[j
].high_bound
+ 1),
(long) (qualifiers
[j
].stride
));
sprintf (p2
, " {%ld bits}", (long) (qualifiers
[j
].stride
));
p2
+= sizeof ("] of ")-1;
/* Print out the global file header for object files. */
char *time
= ctime ((off_t
*)&ptr
->f_timdat
);
ushort flags
= ptr
->f_flags
;
printf("Global file header:\n");
printf(" %-*s 0x%x\n", 24, "magic number", (ushort
) ptr
->f_magic
);
printf(" %-*s %d\n", 24, "# sections", (int) ptr
->f_nscns
);
printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr
->f_timdat
, time
);
printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr
->f_symptr
);
printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr
->f_nsyms
);
printf(" %-*s %ld\n", 24, "optional header", (long) ptr
->f_opthdr
);
printf(" %-*s 0x%lx", 24, "flags", (ushort
) flags
);
if ((flags
& F_RELFLG
) != 0)
if ((flags
& F_EXEC
) != 0)
if ((flags
& F_LNNO
) != 0)
if ((flags
& F_LSYMS
) != 0)
if ((flags
& F_MINMAL
) != 0)
if ((flags
& F_UPDATE
) != 0)
if ((flags
& F_SWABD
) != 0)
if ((flags
& F_AR16WR
) != 0)
if ((flags
& F_AR32WR
) != 0)
if ((flags
& F_AR32W
) != 0)
if ((flags
& F_PATCH
) != 0)
printf (", F_PATCH/F_NODF");
/* Print out the symbolic header. */
printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
(sym_ptr
->vstamp
& 0xffff) >> 8,
printf(" %-*s %11s %11s %11s\n", width
, "Info", "Offset", "Number", "Bytes");
printf(" %-*s %11s %11s %11s\n", width
, "====", "======", "======", "=====\n");
printf(" %-*s %11ld %11d %11d [%d]\n", width
, "Line numbers",
sym_ptr
->cbLineOffset
, sym_ptr
->cbLine
, sym_ptr
->cbLine
, sym_ptr
->ilineMax
);
printf(" %-*s %11ld %11d %11d\n", width
, "Dense numbers",
sym_ptr
->cbDnOffset
, sym_ptr
->idnMax
, sym_ptr
->idnMax
* sizeof (DNR
));
printf(" %-*s %11ld %11d %11d\n", width
, "Procedures Tables",
sym_ptr
->cbPdOffset
, sym_ptr
->ipdMax
, sym_ptr
->ipdMax
* sizeof (PDR
));
printf(" %-*s %11ld %11d %11d\n", width
, "Local Symbols",
sym_ptr
->cbSymOffset
, sym_ptr
->isymMax
, sym_ptr
->isymMax
* sizeof (SYMR
));
printf(" %-*s %11ld %11d %11d\n", width
, "Optimization Symbols",
sym_ptr
->cbOptOffset
, sym_ptr
->ioptMax
, sym_ptr
->ioptMax
* sizeof (OPTR
));
printf(" %-*s %11ld %11d %11d\n", width
, "Auxiliary Symbols",
sym_ptr
->cbAuxOffset
, sym_ptr
->iauxMax
, sym_ptr
->iauxMax
* sizeof (AUXU
));
printf(" %-*s %11ld %11d %11d\n", width
, "Local Strings",
sym_ptr
->cbSsOffset
, sym_ptr
->issMax
, sym_ptr
->issMax
);
printf(" %-*s %11ld %11d %11d\n", width
, "External Strings",
sym_ptr
->cbSsExtOffset
, sym_ptr
->issExtMax
, sym_ptr
->issExtMax
);
printf(" %-*s %11ld %11d %11d\n", width
, "File Tables",
sym_ptr
->cbFdOffset
, sym_ptr
->ifdMax
, sym_ptr
->ifdMax
* sizeof (FDR
));
printf(" %-*s %11ld %11d %11d\n", width
, "Relative Files",
sym_ptr
->cbRfdOffset
, sym_ptr
->crfd
, sym_ptr
->crfd
* sizeof (ulong
));
printf(" %-*s %11ld %11d %11d\n", width
, "External Symbols",
sym_ptr
->cbExtOffset
, sym_ptr
->iextMax
, sym_ptr
->iextMax
* sizeof (EXTR
));
/* Print out a symbol. */
print_symbol (sym_ptr
, number
, strbase
, aux_base
, ifd
)
sc_t storage_class
= (sc_t
) sym_ptr
->sc
;
st_t symbol_type
= (st_t
) sym_ptr
->st
;
ulong index
= sym_ptr
->index
;
char *used_ptr
= aux_used
+ (aux_base
- aux_symbols
);
printf ("\n Symbol# %d: \"%s\"\n", number
, sym_ptr
->iss
+ strbase
);
if (aux_base
!= (AUXU
*)0 && index
!= indexNil
)
printf (" End+1 symbol: %ld\n", index
);
if (free_scope
== (scope_t
*)0)
scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
free_scope
= scope_ptr
->prev
;
scope_ptr
->open_sym
= number
;
scope_ptr
->st
= symbol_type
;
scope_ptr
->sc
= storage_class
;
scope_ptr
->prev
= cur_scope
;
if (storage_class
== sc_Text
|| storage_class
== sc_Info
)
printf (" First symbol: %ld\n", index
);
printf (" First symbol: %ld\n", aux_base
[index
].isym
);
if (cur_scope
== (scope_t
*)0)
printf (" Can't pop end scope\n");
cur_scope
= scope_ptr
->prev
;
scope_ptr
->prev
= free_scope
;
if (MIPS_IS_STAB(sym_ptr
))
else if (ifd
== -1) /* local symbol */
used_ptr
[index
] = used_ptr
[index
+1] = 1;
printf (" End+1 symbol: %-7ld Type: %s\n",
aux_base
[index
].isym
, type_to_string (aux_base
, index
+1));
type_to_string (aux_base
, index
));
if (free_scope
== (scope_t
*)0)
scope_ptr
= (scope_t
*) malloc (sizeof (scope_t
));
free_scope
= scope_ptr
->prev
;
scope_ptr
->open_sym
= number
;
scope_ptr
->st
= symbol_type
;
scope_ptr
->sc
= storage_class
;
scope_ptr
->prev
= cur_scope
;
if (!MIPS_IS_STAB (sym_ptr
))
type_to_string (aux_base
, index
));
if (cur_scope
== (scope_t
*)0)
for (scope_ptr
= cur_scope
;
scope_ptr
!= (scope_t
*)0;
scope_ptr
= scope_ptr
->prev
)
if (scope_ptr
->st
== st_Proc
|| scope_ptr
->st
== st_StaticProc
)
else if (scope_ptr
->st
== st_File
)
else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Text
)
else if (scope_ptr
->st
== st_Block
&& scope_ptr
->sc
== sc_Info
)
printf (" %d [%s]", scope_ptr
->open_sym
, class);
printf (" Value: %-13ld ",
printf ("String index: %ld\n", (long)sym_ptr
->iss
);
printf ("String index: %-11ld Ifd: %d\n",
(long)sym_ptr
->iss
, ifd
);
printf (" Symbol type: %-11sStorage class: %-11s",
st_to_string (symbol_type
), sc_to_string (storage_class
));
if (MIPS_IS_STAB(sym_ptr
))
register int i
= sizeof(stab_names
) / sizeof(stab_names
[0]);
char *stab_name
= "stab";
short code
= MIPS_UNMARK_STAB(sym_ptr
->index
);
if (stab_names
[i
].code
== code
)
stab_name
= stab_names
[i
].string
;
printf ("Index: 0x%lx (%s)\n", (long)sym_ptr
->index
, stab_name
);
else if (sym_ptr
->st
== stLabel
&& sym_ptr
->index
!= indexNil
)
printf ("Index: %ld (line#)\n", (long)sym_ptr
->index
);
printf ("Index: %ld\n", (long)sym_ptr
->index
);
/* Print out a word from the aux. table in various formats. */
print_aux (u
, auxi
, used
)
printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
/* Write aggregate information to a string. */
emit_aggregate (string
, u
, u2
, which
)
int index
= u
.rndx
.index
;
sym_base
= file_desc
[ifd
].isymBase
;
ss_base
= file_desc
[ifd
].issBase
;
name
= (index
== indexNil
) ? 0 : l_symbols
[index
+ sym_base
].iss
;
"%s %s { ifd = %d, index = %d }",
(name
== 0) ? "/* no name */" : &l_strings
[ ss_base
+ name
],
/* Print out information about a file descriptor, and the symbols,
procedures, and line numbers within it. */
print_file_desc (fdp
, number
)
str_base
= l_strings
+ fdp
->issBase
;
aux_base
= aux_symbols
+ fdp
->iauxBase
;
used_base
= aux_used
+ (aux_base
- aux_symbols
);
printf ("\nFile #%d, \"%s\"\n\n", number
, str_base
+ fdp
->rss
);
printf (" Name index = %-10d Readin = %s\n",
(long) fdp
->rss
, (fdp
->fReadin
) ? "Yes" : "No");
printf (" Merge = %-10s Endian = %s\n",
(fdp
->fMerge
) ? "Yes" : "No",
(fdp
->fBigendian
) ? "BIG" : "LITTLE");
printf (" Debug level = %-10s Language = %s\n",
glevel_to_string (fdp
->glevel
),
lang_to_string((lang_t
) fdp
->lang
));
printf (" Adr = 0x%08lx\n\n", (long) fdp
->adr
);
printf(" %-*s %11s %11s %11s %11s\n", width
, "Info", "Start", "Number", "Size", "Offset");
printf(" %-*s %11s %11s %11s %11s\n", width
, "====", "=====", "======", "====", "======");
printf(" %-*s %11lu %11lu %11lu %11lu\n",
(ulong
) (fdp
->issBase
+ sym_hdr
.cbSsOffset
));
printf(" %-*s %11lu %11u %11u %11lu\n",
(ulong
) (fdp
->csym
* sizeof (SYMR
)),
(ulong
) (fdp
->isymBase
* sizeof (SYMR
) + sym_hdr
.cbSymOffset
));
printf(" %-*s %11lu %11lu %11lu %11lu\n",
(ulong
) fdp
->cbLineOffset
,
(ulong
) (fdp
->cbLineOffset
+ sym_hdr
.cbLineOffset
));
printf(" %-*s %11lu %11lu %11lu %11lu\n",
width
, "Optimization symbols",
(ulong
) (fdp
->copt
* sizeof (OPTR
)),
(ulong
) (fdp
->ioptBase
* sizeof (OPTR
) + sym_hdr
.cbOptOffset
));
printf(" %-*s %11llu %11lu %11lu %11lu\n",
(ulong
) (fdp
->cpd
* sizeof (PDR
)),
(ulong
) (fdp
->ipdFirst
* sizeof (PDR
) + sym_hdr
.cbPdOffset
));
printf(" %-*s %11lu %11lu %11lu %11lu\n",
width
, "Auxiliary symbols",
(ulong
) (fdp
->caux
* sizeof (AUXU
)),
(ulong
) (fdp
->iauxBase
* sizeof(AUXU
) + sym_hdr
.cbAuxOffset
));
printf(" %-*s %11lu %11lu %11lu %11lu\n",
(ulong
) (fdp
->crfd
* sizeof (ulong
)),
(ulong
) (fdp
->rfdBase
* sizeof(ulong
) + sym_hdr
.cbRfdOffset
));
if (want_scope
&& cur_scope
!= (scope_t
*)0)
printf ("\n Warning scope does not start at 0!\n");
* print the info about the symbol table.
printf ("\n There are %lu local symbols, starting at %lu\n",
(ulong
) (fdp
->isymBase
+ sym_hdr
.cbSymOffset
));
for(symi
= fdp
->isymBase
; symi
< (fdp
->csym
+ fdp
->isymBase
); symi
++)
print_symbol (&l_symbols
[symi
],
if (want_scope
&& cur_scope
!= (scope_t
*)0)
printf ("\n Warning scope does not end at 0!\n");
* print the aux. table if desired.
if (want_aux
&& fdp
->caux
!= 0)
printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
(ulong
) (fdp
->iauxBase
+ sym_hdr
.cbAuxOffset
));
for (auxi
= fdp
->iauxBase
; auxi
< (fdp
->caux
+ fdp
->iauxBase
); auxi
++)
print_aux (aux_base
[auxi
], auxi
, used_base
[auxi
]);
* print the relative file descriptors.
if (want_rfd
&& fdp
->crfd
!= 0)
printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
rfd_ptr
= rfile_desc
+ fdp
->rfdBase
* sizeof (ulong
);
for (i
= 0; i
< fdp
->crfd
; i
++)
printf ("\t#%-5ld %11ld, 0x%08lx\n", i
, *rfd_ptr
, *rfd_ptr
);
* do the procedure descriptors.
printf ("\n There are %lu procedure descriptor entries, ", (ulong
) fdp
->cpd
);
printf ("starting at %lu.\n", (ulong
) fdp
->ipdFirst
);
for (pdi
= fdp
->ipdFirst
; pdi
< (fdp
->cpd
+ fdp
->ipdFirst
); pdi
++)
PDR
*proc_ptr
= &proc_desc
[pdi
];
printf ("\n\tProcedure descriptor %d:\n", (pdi
- fdp
->ipdFirst
));
printf ("\t Name index = %-11ld Name = \"%s\"\n",
(long) l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
,
l_symbols
[proc_ptr
->isym
+ fdp
->isymBase
].iss
+ str_base
);
printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
(long) proc_ptr
->regmask
,
(long) proc_ptr
->regoffset
,
(long) proc_ptr
->fregmask
,
(long) proc_ptr
->fregoffset
);
printf ("\t .frame $%d,%ld,$%d\n",
(int) proc_ptr
->framereg
,
(long) proc_ptr
->frameoffset
,
printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
printf ("\t First line # = %-11ld Last line # = %ld\n",
(long) proc_ptr
->lnHigh
);
printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
(long) proc_ptr
->cbLineOffset
,
* print the line number entries.
if (want_line
&& fdp
->cline
!= 0)
long cur_line
= proc_ptr
->lnLow
;
uchar
*line_ptr
= ((uchar
*)lines
) + proc_ptr
->cbLineOffset
;
if (pdi
== fdp
->cpd
+ fdp
->ipdFirst
- 1) /* last procedure */
line_end
= ((uchar
*)lines
) + fdp
->cbLine
+ fdp
->ilineBase
;
else /* not last proc. */
line_end
= ((uchar
*)lines
) + proc_desc
[pdi
+1].cbLineOffset
;
printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
(ulong
) (line_end
- line_ptr
),
(ulong
) (fdp
->ilineBase
+ sym_hdr
.cbLineOffset
));
while (line_ptr
< line_end
)
{ /* sign extend nibble */
delta
= ((*line_ptr
>> 4) ^ 0x8) - 0x8;
count
= (*line_ptr
& 0xf) + 1;
delta
= (((line_ptr
[1]) & 0xff) << 8) + ((line_ptr
[2]) & 0xff);
delta
= (delta
^ 0x8000) - 0x8000;
printf ("\t Line %11ld, delta %5d, count %2d\n",
/* Read in the portions of the .T file that we will print out. */
read_tfile
__proto((void))
off_t sym_hdr_offset
= 0;
/* Determine if this is a .T file (which has no file header), or some
sort of object file (which does have a file header) via the magic
(void) read_seek ((PTR_T
) &magic
, sizeof (magic
), (off_t
)0, "Magic number");
if (magic
== MIPSELMAGIC
|| magic
== MIPSEBMAGIC
)
(void) read_seek ((PTR_T
) &global_hdr
, sizeof (global_hdr
), (off_t
)0,
print_global_hdr (&global_hdr
);
if (global_hdr
.f_symptr
== 0)
printf ("No symbolic header, Goodbye!\n");
sym_hdr_offset
= global_hdr
.f_symptr
;
(void) read_seek ((PTR_T
) &sym_hdr
,
print_sym_hdr (&sym_hdr
);
lines
= (LINER
*) read_seek ((PTR_T
)0,
dense_nums
= (DNR
*) read_seek ((PTR_T
)0,
sym_hdr
.idnMax
* sizeof (DNR
),
proc_desc
= (PDR
*) read_seek ((PTR_T
)0,
sym_hdr
.ipdMax
* sizeof (PDR
),
l_symbols
= (SYMR
*) read_seek ((PTR_T
)0,
sym_hdr
.isymMax
* sizeof (SYMR
),
opt_symbols
= (OPTR
*) read_seek ((PTR_T
)0,
sym_hdr
.ioptMax
* sizeof (OPTR
),
aux_symbols
= (AUXU
*) read_seek ((PTR_T
)0,
sym_hdr
.iauxMax
* sizeof (AUXU
),
aux_used
= calloc (sym_hdr
.iauxMax
, 1);
if (aux_used
== (char *)0)
l_strings
= (char *) read_seek ((PTR_T
)0,
e_strings
= (char *) read_seek ((PTR_T
)0,
"External string table");
file_desc
= (FDR
*) read_seek ((PTR_T
)0,
sym_hdr
.ifdMax
* sizeof (FDR
),
rfile_desc
= (ulong
*) read_seek ((PTR_T
)0,
sym_hdr
.crfd
* sizeof (ulong
),
e_symbols
= (EXTR
*) read_seek ((PTR_T
)0,
sym_hdr
.iextMax
* sizeof (EXTR
),
while ((opt
= getopt (argc
, argv
, "alrs")) != EOF
)
default: errors
++; break;
case 'a': want_aux
++; break; /* print aux table */
case 'l': want_line
++; break; /* print line numbers */
case 'r': want_rfd
++; break; /* print relative fd's */
case 's': want_scope
++; break; /* print scope info */
if (errors
|| optind
!= argc
- 1)
fprintf (stderr
, "Calling Sequence:\n");
fprintf (stderr
, "\t%0 [-alrs] <object-or-T-file>\n", argv
[0]);
fprintf (stderr
, "switches:\n");
fprintf (stderr
, "\t-a Print out auxiliary table.\n");
fprintf (stderr
, "\t-l Print out line numbers.\n");
fprintf (stderr
, "\t-r Print out relative file descriptors.\n");
fprintf (stderr
, "\t-s Print out the current scopes for an item.\n");
* Open and process the input file.
tfile_fd
= open (argv
[optind
], O_RDONLY
);
* Print any global aux words if any.
if (sym_hdr
.ifdMax
!= 0 && file_desc
[0].iauxBase
!= 0)
printf ("\nGlobal auxiliary entries before first file:\n");
for (i
= 0; i
< file_desc
[0].iauxBase
; i
++)
print_aux (aux_symbols
[i
], 0, aux_used
[i
]);
file_desc
[sym_hdr
.ifdMax
-1].iauxBase
+
file_desc
[sym_hdr
.ifdMax
-1].caux
- 1;
if (last_aux_in_use
< sym_hdr
.iauxMax
-1)
printf ("\nGlobal auxiliary entries after last file:\n");
for (i
= last_aux_in_use
; i
< sym_hdr
.iauxMax
; i
++)
print_aux (aux_symbols
[i
], i
- last_aux_in_use
, aux_used
[i
]);
* Print the information for each file.
for (i
= 0; i
< sym_hdr
.ifdMax
; i
++)
print_file_desc (&file_desc
[i
], i
);
* Print the external symbols.
want_scope
= 0; /* scope info is meaning for extern symbols */
printf ("\nThere are %lu external symbols, starting at %lu\n",
(ulong
) sym_hdr
.cbExtOffset
);
for(i
= 0; i
< sym_hdr
.iextMax
; i
++)
print_symbol (&e_symbols
[i
].asym
, i
, e_strings
,
aux_symbols
+ file_desc
[e_symbols
[i
].ifd
].iauxBase
,
* Print unused aux symbols now.
for (i
= 0; i
< sym_hdr
.iauxMax
; i
++)
printf ("\nThe following auxiliary table entries were unused:\n\n");
printf (" #%-5d %11ld 0x%08lx %s\n",
(long) aux_symbols
[i
].isym
,
(long) aux_symbols
[i
].isym
,
type_to_string (aux_symbols
, i
));
fprintf (stderr
, "mips-tdump internal error");
fprintf(stderr
, "%s\n", s
);
/* Same as `malloc' but report error if no memory available. */
register PTR_T value
= malloc (size
);
fatal ("Virtual memory exhausted.");