| 1 |
280 |
jeremybenn |
/* Read and manage MIPS symbol tables from object modules.
|
| 2 |
|
|
Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
|
| 3 |
|
|
2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
| 4 |
|
|
Contributed by hartzell@boulder.colorado.edu,
|
| 5 |
|
|
Rewritten by meissner@osf.org.
|
| 6 |
|
|
|
| 7 |
|
|
This file is part of GCC.
|
| 8 |
|
|
|
| 9 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
| 10 |
|
|
the terms of the GNU General Public License as published by the Free
|
| 11 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
| 12 |
|
|
version.
|
| 13 |
|
|
|
| 14 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
| 15 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 16 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
| 17 |
|
|
for more details.
|
| 18 |
|
|
|
| 19 |
|
|
You should have received a copy of the GNU General Public License
|
| 20 |
|
|
along with GCC; see the file COPYING3. If not see
|
| 21 |
|
|
<http://www.gnu.org/licenses/>. */
|
| 22 |
|
|
|
| 23 |
|
|
#include "config.h"
|
| 24 |
|
|
#include "system.h"
|
| 25 |
|
|
#include "coretypes.h"
|
| 26 |
|
|
#include "tm.h"
|
| 27 |
|
|
#include "version.h"
|
| 28 |
|
|
#ifdef index
|
| 29 |
|
|
#undef index
|
| 30 |
|
|
#endif
|
| 31 |
|
|
#ifndef CROSS_DIRECTORY_STRUCTURE
|
| 32 |
|
|
#include <a.out.h>
|
| 33 |
|
|
#else
|
| 34 |
|
|
#include "mips/a.out.h"
|
| 35 |
|
|
#endif /* CROSS_DIRECTORY_STRUCTURE */
|
| 36 |
|
|
|
| 37 |
|
|
/* Include getopt.h for the sake of getopt_long. */
|
| 38 |
|
|
#include "getopt.h"
|
| 39 |
|
|
|
| 40 |
|
|
#ifndef MIPS_IS_STAB
|
| 41 |
|
|
/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
|
| 42 |
|
|
and mips-tdump.c to print them out. This is used on the Alpha,
|
| 43 |
|
|
which does not include mips.h.
|
| 44 |
|
|
|
| 45 |
|
|
These must match the corresponding definitions in gdb/mipsread.c.
|
| 46 |
|
|
Unfortunately, gcc and gdb do not currently share any directories. */
|
| 47 |
|
|
|
| 48 |
|
|
#define CODE_MASK 0x8F300
|
| 49 |
|
|
#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
|
| 50 |
|
|
#define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
|
| 51 |
|
|
#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
|
| 52 |
|
|
#endif
|
| 53 |
|
|
|
| 54 |
|
|
#define uchar unsigned char
|
| 55 |
|
|
#define ushort unsigned short
|
| 56 |
|
|
#define uint unsigned int
|
| 57 |
|
|
#define ulong unsigned long
|
| 58 |
|
|
|
| 59 |
|
|
|
| 60 |
|
|
/* Redefinition of storage classes as an enumeration for better
|
| 61 |
|
|
debugging. */
|
| 62 |
|
|
|
| 63 |
|
|
#ifndef stStaParam
|
| 64 |
|
|
#define stStaParam 16 /* Fortran static parameters */
|
| 65 |
|
|
#endif
|
| 66 |
|
|
|
| 67 |
|
|
#ifndef btVoid
|
| 68 |
|
|
#define btVoid 26 /* void basic type */
|
| 69 |
|
|
#endif
|
| 70 |
|
|
|
| 71 |
|
|
typedef enum sc {
|
| 72 |
|
|
sc_Nil = scNil, /* no storage class */
|
| 73 |
|
|
sc_Text = scText, /* text symbol */
|
| 74 |
|
|
sc_Data = scData, /* initialized data symbol */
|
| 75 |
|
|
sc_Bss = scBss, /* un-initialized data symbol */
|
| 76 |
|
|
sc_Register = scRegister, /* value of symbol is register number */
|
| 77 |
|
|
sc_Abs = scAbs, /* value of symbol is absolute */
|
| 78 |
|
|
sc_Undefined = scUndefined, /* who knows? */
|
| 79 |
|
|
sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
|
| 80 |
|
|
sc_Bits = scBits, /* this is a bit field */
|
| 81 |
|
|
sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */
|
| 82 |
|
|
sc_RegImage = scRegImage, /* register value saved on stack */
|
| 83 |
|
|
sc_Info = scInfo, /* symbol contains debugger information */
|
| 84 |
|
|
sc_UserStruct = scUserStruct, /* addr in struct user for current process */
|
| 85 |
|
|
sc_SData = scSData, /* load time only small data */
|
| 86 |
|
|
sc_SBss = scSBss, /* load time only small common */
|
| 87 |
|
|
sc_RData = scRData, /* load time only read only data */
|
| 88 |
|
|
sc_Var = scVar, /* Var parameter (fortran,pascal) */
|
| 89 |
|
|
sc_Common = scCommon, /* common variable */
|
| 90 |
|
|
sc_SCommon = scSCommon, /* small common */
|
| 91 |
|
|
sc_VarRegister = scVarRegister, /* Var parameter in a register */
|
| 92 |
|
|
sc_Variant = scVariant, /* Variant record */
|
| 93 |
|
|
sc_SUndefined = scSUndefined, /* small undefined(external) data */
|
| 94 |
|
|
sc_Init = scInit, /* .init section symbol */
|
| 95 |
|
|
sc_Max = scMax /* Max storage class+1 */
|
| 96 |
|
|
} sc_t;
|
| 97 |
|
|
|
| 98 |
|
|
/* Redefinition of symbol type. */
|
| 99 |
|
|
|
| 100 |
|
|
typedef enum st {
|
| 101 |
|
|
st_Nil = stNil, /* Nuthin' special */
|
| 102 |
|
|
st_Global = stGlobal, /* external symbol */
|
| 103 |
|
|
st_Static = stStatic, /* static */
|
| 104 |
|
|
st_Param = stParam, /* procedure argument */
|
| 105 |
|
|
st_Local = stLocal, /* local variable */
|
| 106 |
|
|
st_Label = stLabel, /* label */
|
| 107 |
|
|
st_Proc = stProc, /* " " Procedure */
|
| 108 |
|
|
st_Block = stBlock, /* beginning of block */
|
| 109 |
|
|
st_End = stEnd, /* end (of anything) */
|
| 110 |
|
|
st_Member = stMember, /* member (of anything - struct/union/enum */
|
| 111 |
|
|
st_Typedef = stTypedef, /* type definition */
|
| 112 |
|
|
st_File = stFile, /* file name */
|
| 113 |
|
|
st_RegReloc = stRegReloc, /* register relocation */
|
| 114 |
|
|
st_Forward = stForward, /* forwarding address */
|
| 115 |
|
|
st_StaticProc = stStaticProc, /* load time only static procs */
|
| 116 |
|
|
st_StaParam = stStaParam, /* Fortran static parameters */
|
| 117 |
|
|
st_Constant = stConstant, /* const */
|
| 118 |
|
|
#ifdef stStruct
|
| 119 |
|
|
st_Struct = stStruct, /* struct */
|
| 120 |
|
|
st_Union = stUnion, /* union */
|
| 121 |
|
|
st_Enum = stEnum, /* enum */
|
| 122 |
|
|
#endif
|
| 123 |
|
|
st_Str = stStr, /* string */
|
| 124 |
|
|
st_Number = stNumber, /* pure number (i.e. 4 NOR 2+2) */
|
| 125 |
|
|
st_Expr = stExpr, /* 2+2 vs. 4 */
|
| 126 |
|
|
st_Type = stType, /* post-coercion SER */
|
| 127 |
|
|
st_Max = stMax /* max type+1 */
|
| 128 |
|
|
} st_t;
|
| 129 |
|
|
|
| 130 |
|
|
/* Redefinition of type qualifiers. */
|
| 131 |
|
|
|
| 132 |
|
|
typedef enum tq {
|
| 133 |
|
|
tq_Nil = tqNil, /* bt is what you see */
|
| 134 |
|
|
tq_Ptr = tqPtr, /* pointer */
|
| 135 |
|
|
tq_Proc = tqProc, /* procedure */
|
| 136 |
|
|
tq_Array = tqArray, /* duh */
|
| 137 |
|
|
tq_Far = tqFar, /* longer addressing - 8086/8 land */
|
| 138 |
|
|
tq_Vol = tqVol, /* volatile */
|
| 139 |
|
|
tq_Max = tqMax /* Max type qualifier+1 */
|
| 140 |
|
|
} tq_t;
|
| 141 |
|
|
|
| 142 |
|
|
/* Redefinition of basic types. */
|
| 143 |
|
|
|
| 144 |
|
|
typedef enum bt {
|
| 145 |
|
|
bt_Nil = btNil, /* undefined */
|
| 146 |
|
|
bt_Adr = btAdr, /* address - integer same size as pointer */
|
| 147 |
|
|
bt_Char = btChar, /* character */
|
| 148 |
|
|
bt_UChar = btUChar, /* unsigned character */
|
| 149 |
|
|
bt_Short = btShort, /* short */
|
| 150 |
|
|
bt_UShort = btUShort, /* unsigned short */
|
| 151 |
|
|
bt_Int = btInt, /* int */
|
| 152 |
|
|
bt_UInt = btUInt, /* unsigned int */
|
| 153 |
|
|
bt_Long = btLong, /* long */
|
| 154 |
|
|
bt_ULong = btULong, /* unsigned long */
|
| 155 |
|
|
bt_Float = btFloat, /* float (real) */
|
| 156 |
|
|
bt_Double = btDouble, /* Double (real) */
|
| 157 |
|
|
bt_Struct = btStruct, /* Structure (Record) */
|
| 158 |
|
|
bt_Union = btUnion, /* Union (variant) */
|
| 159 |
|
|
bt_Enum = btEnum, /* Enumerated */
|
| 160 |
|
|
bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
|
| 161 |
|
|
bt_Range = btRange, /* subrange of int */
|
| 162 |
|
|
bt_Set = btSet, /* pascal sets */
|
| 163 |
|
|
bt_Complex = btComplex, /* fortran complex */
|
| 164 |
|
|
bt_DComplex = btDComplex, /* fortran double complex */
|
| 165 |
|
|
bt_Indirect = btIndirect, /* forward or unnamed typedef */
|
| 166 |
|
|
bt_FixedDec = btFixedDec, /* Fixed Decimal */
|
| 167 |
|
|
bt_FloatDec = btFloatDec, /* Float Decimal */
|
| 168 |
|
|
bt_String = btString, /* Varying Length Character String */
|
| 169 |
|
|
bt_Bit = btBit, /* Aligned Bit String */
|
| 170 |
|
|
bt_Picture = btPicture, /* Picture */
|
| 171 |
|
|
bt_Void = btVoid, /* void */
|
| 172 |
|
|
bt_Max = btMax /* Max basic type+1 */
|
| 173 |
|
|
} bt_t;
|
| 174 |
|
|
|
| 175 |
|
|
/* Redefinition of the language codes. */
|
| 176 |
|
|
|
| 177 |
|
|
typedef enum lang {
|
| 178 |
|
|
lang_C = langC,
|
| 179 |
|
|
lang_Pascal = langPascal,
|
| 180 |
|
|
lang_Fortran = langFortran,
|
| 181 |
|
|
lang_Assembler = langAssembler,
|
| 182 |
|
|
lang_Machine = langMachine,
|
| 183 |
|
|
lang_Nil = langNil,
|
| 184 |
|
|
lang_Ada = langAda,
|
| 185 |
|
|
lang_Pl1 = langPl1,
|
| 186 |
|
|
lang_Cobol = langCobol
|
| 187 |
|
|
} lang_t;
|
| 188 |
|
|
|
| 189 |
|
|
/* Redefinition of the debug level codes. */
|
| 190 |
|
|
|
| 191 |
|
|
typedef enum glevel {
|
| 192 |
|
|
glevel_0 = GLEVEL_0,
|
| 193 |
|
|
glevel_1 = GLEVEL_1,
|
| 194 |
|
|
glevel_2 = GLEVEL_2,
|
| 195 |
|
|
glevel_3 = GLEVEL_3
|
| 196 |
|
|
} glevel_t;
|
| 197 |
|
|
|
| 198 |
|
|
|
| 199 |
|
|
/* Keep track of the active scopes. */
|
| 200 |
|
|
typedef struct scope {
|
| 201 |
|
|
struct scope *prev; /* previous scope */
|
| 202 |
|
|
ulong open_sym; /* symbol opening scope */
|
| 203 |
|
|
sc_t sc; /* storage class */
|
| 204 |
|
|
st_t st; /* symbol type */
|
| 205 |
|
|
} scope_t;
|
| 206 |
|
|
|
| 207 |
|
|
struct filehdr global_hdr; /* a.out header */
|
| 208 |
|
|
|
| 209 |
|
|
int errors = 0; /* # of errors */
|
| 210 |
|
|
int want_aux = 0; /* print aux table */
|
| 211 |
|
|
int want_line = 0; /* print line numbers */
|
| 212 |
|
|
int want_rfd = 0; /* print relative file desc's */
|
| 213 |
|
|
int want_scope = 0; /* print scopes for every symbol */
|
| 214 |
|
|
int tfile = 0; /* no global header file */
|
| 215 |
|
|
int version = 0; /* print version # */
|
| 216 |
|
|
int verbose = 0;
|
| 217 |
|
|
int tfile_fd; /* file descriptor of .T file */
|
| 218 |
|
|
off_t tfile_offset; /* current offset in .T file */
|
| 219 |
|
|
scope_t *cur_scope = 0; /* list of active scopes */
|
| 220 |
|
|
scope_t *free_scope = 0; /* list of freed scopes */
|
| 221 |
|
|
HDRR sym_hdr; /* symbolic header */
|
| 222 |
|
|
char *l_strings; /* local strings */
|
| 223 |
|
|
char *e_strings; /* external strings */
|
| 224 |
|
|
SYMR *l_symbols; /* local symbols */
|
| 225 |
|
|
EXTR *e_symbols; /* external symbols */
|
| 226 |
|
|
LINER *lines; /* line numbers */
|
| 227 |
|
|
DNR *dense_nums; /* dense numbers */
|
| 228 |
|
|
OPTR *opt_symbols; /* optimization symbols */
|
| 229 |
|
|
AUXU *aux_symbols; /* Auxiliary symbols */
|
| 230 |
|
|
char *aux_used; /* map of which aux syms are used */
|
| 231 |
|
|
FDR *file_desc; /* file tables */
|
| 232 |
|
|
ulong *rfile_desc; /* relative file tables */
|
| 233 |
|
|
PDR *proc_desc; /* procedure tables */
|
| 234 |
|
|
|
| 235 |
|
|
/* Forward reference for functions. */
|
| 236 |
|
|
static void *read_seek (void *, size_t, off_t, const char *);
|
| 237 |
|
|
static void read_tfile (void);
|
| 238 |
|
|
static void print_global_hdr (struct filehdr *);
|
| 239 |
|
|
static void print_sym_hdr (HDRR *);
|
| 240 |
|
|
static void print_file_desc (FDR *, int);
|
| 241 |
|
|
static void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
|
| 242 |
|
|
static void print_aux (AUXU, int, int);
|
| 243 |
|
|
static void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
|
| 244 |
|
|
static const char *st_to_string (st_t);
|
| 245 |
|
|
static const char *sc_to_string (sc_t);
|
| 246 |
|
|
static const char *glevel_to_string (glevel_t);
|
| 247 |
|
|
static const char *lang_to_string (lang_t);
|
| 248 |
|
|
static const char *type_to_string (AUXU *, int, FDR *);
|
| 249 |
|
|
|
| 250 |
|
|
extern char *optarg;
|
| 251 |
|
|
extern int optind;
|
| 252 |
|
|
extern int opterr;
|
| 253 |
|
|
|
| 254 |
|
|
/* Create a table of debugging stab-codes and corresponding names. */
|
| 255 |
|
|
|
| 256 |
|
|
#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
|
| 257 |
|
|
const struct {const short code; const char string[10];} stab_names[] = {
|
| 258 |
|
|
#include "stab.def"
|
| 259 |
|
|
#undef __define_stab
|
| 260 |
|
|
};
|
| 261 |
|
|
|
| 262 |
|
|
/* Command line options for getopt_long. */
|
| 263 |
|
|
|
| 264 |
|
|
static const struct option options[] =
|
| 265 |
|
|
{
|
| 266 |
|
|
{ "version", 0, 0, 'V' },
|
| 267 |
|
|
{ "verbose", 0, 0, 'v' },
|
| 268 |
|
|
{ 0, 0, 0, 0 }
|
| 269 |
|
|
};
|
| 270 |
|
|
|
| 271 |
|
|
/* Read some bytes at a specified location, and return a pointer.
|
| 272 |
|
|
Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE
|
| 273 |
|
|
bytes from offset OFFSET. In case of errors CONTEXT is used as
|
| 274 |
|
|
error message. */
|
| 275 |
|
|
|
| 276 |
|
|
static void *
|
| 277 |
|
|
read_seek (void *ptr, size_t size, off_t offset, const char *context)
|
| 278 |
|
|
{
|
| 279 |
|
|
long read_size = 0;
|
| 280 |
|
|
|
| 281 |
|
|
if (size == 0) /* nothing to read */
|
| 282 |
|
|
return ptr;
|
| 283 |
|
|
|
| 284 |
|
|
if (!ptr)
|
| 285 |
|
|
ptr = xmalloc (size);
|
| 286 |
|
|
|
| 287 |
|
|
if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
|
| 288 |
|
|
|| (read_size = read (tfile_fd, ptr, size)) < 0)
|
| 289 |
|
|
{
|
| 290 |
|
|
perror (context);
|
| 291 |
|
|
exit (1);
|
| 292 |
|
|
}
|
| 293 |
|
|
|
| 294 |
|
|
if (read_size != (long) size)
|
| 295 |
|
|
{
|
| 296 |
|
|
fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
|
| 297 |
|
|
context, read_size, (long) size);
|
| 298 |
|
|
exit (1);
|
| 299 |
|
|
}
|
| 300 |
|
|
|
| 301 |
|
|
tfile_offset = offset + size;
|
| 302 |
|
|
return ptr;
|
| 303 |
|
|
}
|
| 304 |
|
|
|
| 305 |
|
|
|
| 306 |
|
|
/* Convert language code to string format. */
|
| 307 |
|
|
|
| 308 |
|
|
static const char *
|
| 309 |
|
|
lang_to_string (lang_t lang)
|
| 310 |
|
|
{
|
| 311 |
|
|
switch (lang)
|
| 312 |
|
|
{
|
| 313 |
|
|
case langC: return "C";
|
| 314 |
|
|
case langPascal: return "Pascal";
|
| 315 |
|
|
case langFortran: return "Fortran";
|
| 316 |
|
|
case langAssembler: return "Assembler";
|
| 317 |
|
|
case langMachine: return "Machine";
|
| 318 |
|
|
case langNil: return "Nil";
|
| 319 |
|
|
case langAda: return "Ada";
|
| 320 |
|
|
case langPl1: return "Pl1";
|
| 321 |
|
|
case langCobol: return "Cobol";
|
| 322 |
|
|
}
|
| 323 |
|
|
|
| 324 |
|
|
return "Unknown language";
|
| 325 |
|
|
}
|
| 326 |
|
|
|
| 327 |
|
|
|
| 328 |
|
|
/* Convert storage class to string. */
|
| 329 |
|
|
|
| 330 |
|
|
static const char *
|
| 331 |
|
|
sc_to_string (sc_t storage_class)
|
| 332 |
|
|
{
|
| 333 |
|
|
switch(storage_class)
|
| 334 |
|
|
{
|
| 335 |
|
|
case sc_Nil: return "Nil";
|
| 336 |
|
|
case sc_Text: return "Text";
|
| 337 |
|
|
case sc_Data: return "Data";
|
| 338 |
|
|
case sc_Bss: return "Bss";
|
| 339 |
|
|
case sc_Register: return "Register";
|
| 340 |
|
|
case sc_Abs: return "Abs";
|
| 341 |
|
|
case sc_Undefined: return "Undefined";
|
| 342 |
|
|
case sc_CdbLocal: return "CdbLocal";
|
| 343 |
|
|
case sc_Bits: return "Bits";
|
| 344 |
|
|
case sc_CdbSystem: return "CdbSystem";
|
| 345 |
|
|
case sc_RegImage: return "RegImage";
|
| 346 |
|
|
case sc_Info: return "Info";
|
| 347 |
|
|
case sc_UserStruct: return "UserStruct";
|
| 348 |
|
|
case sc_SData: return "SData";
|
| 349 |
|
|
case sc_SBss: return "SBss";
|
| 350 |
|
|
case sc_RData: return "RData";
|
| 351 |
|
|
case sc_Var: return "Var";
|
| 352 |
|
|
case sc_Common: return "Common";
|
| 353 |
|
|
case sc_SCommon: return "SCommon";
|
| 354 |
|
|
case sc_VarRegister: return "VarRegister";
|
| 355 |
|
|
case sc_Variant: return "Variant";
|
| 356 |
|
|
case sc_SUndefined: return "SUndefined";
|
| 357 |
|
|
case sc_Init: return "Init";
|
| 358 |
|
|
case sc_Max: return "Max";
|
| 359 |
|
|
}
|
| 360 |
|
|
|
| 361 |
|
|
return "???";
|
| 362 |
|
|
}
|
| 363 |
|
|
|
| 364 |
|
|
|
| 365 |
|
|
/* Convert symbol type to string. */
|
| 366 |
|
|
|
| 367 |
|
|
static const char *
|
| 368 |
|
|
st_to_string (st_t symbol_type)
|
| 369 |
|
|
{
|
| 370 |
|
|
switch(symbol_type)
|
| 371 |
|
|
{
|
| 372 |
|
|
case st_Nil: return "Nil";
|
| 373 |
|
|
case st_Global: return "Global";
|
| 374 |
|
|
case st_Static: return "Static";
|
| 375 |
|
|
case st_Param: return "Param";
|
| 376 |
|
|
case st_Local: return "Local";
|
| 377 |
|
|
case st_Label: return "Label";
|
| 378 |
|
|
case st_Proc: return "Proc";
|
| 379 |
|
|
case st_Block: return "Block";
|
| 380 |
|
|
case st_End: return "End";
|
| 381 |
|
|
case st_Member: return "Member";
|
| 382 |
|
|
case st_Typedef: return "Typedef";
|
| 383 |
|
|
case st_File: return "File";
|
| 384 |
|
|
case st_RegReloc: return "RegReloc";
|
| 385 |
|
|
case st_Forward: return "Forward";
|
| 386 |
|
|
case st_StaticProc: return "StaticProc";
|
| 387 |
|
|
case st_Constant: return "Constant";
|
| 388 |
|
|
case st_StaParam: return "StaticParam";
|
| 389 |
|
|
#ifdef stStruct
|
| 390 |
|
|
case st_Struct: return "Struct";
|
| 391 |
|
|
case st_Union: return "Union";
|
| 392 |
|
|
case st_Enum: return "Enum";
|
| 393 |
|
|
#endif
|
| 394 |
|
|
case st_Str: return "String";
|
| 395 |
|
|
case st_Number: return "Number";
|
| 396 |
|
|
case st_Expr: return "Expr";
|
| 397 |
|
|
case st_Type: return "Type";
|
| 398 |
|
|
case st_Max: return "Max";
|
| 399 |
|
|
}
|
| 400 |
|
|
|
| 401 |
|
|
return "???";
|
| 402 |
|
|
}
|
| 403 |
|
|
|
| 404 |
|
|
|
| 405 |
|
|
/* Convert debug level to string. */
|
| 406 |
|
|
|
| 407 |
|
|
static const char *
|
| 408 |
|
|
glevel_to_string (glevel_t g_level)
|
| 409 |
|
|
{
|
| 410 |
|
|
switch(g_level)
|
| 411 |
|
|
{
|
| 412 |
|
|
case GLEVEL_0: return "G0";
|
| 413 |
|
|
case GLEVEL_1: return "G1";
|
| 414 |
|
|
case GLEVEL_2: return "G2";
|
| 415 |
|
|
case GLEVEL_3: return "G3";
|
| 416 |
|
|
}
|
| 417 |
|
|
|
| 418 |
|
|
return "??";
|
| 419 |
|
|
}
|
| 420 |
|
|
|
| 421 |
|
|
|
| 422 |
|
|
/* Convert the type information to string format. */
|
| 423 |
|
|
|
| 424 |
|
|
static const char *
|
| 425 |
|
|
type_to_string (AUXU *aux_ptr, int index, FDR *fdp)
|
| 426 |
|
|
{
|
| 427 |
|
|
AUXU u;
|
| 428 |
|
|
struct qual {
|
| 429 |
|
|
tq_t type;
|
| 430 |
|
|
int low_bound;
|
| 431 |
|
|
int high_bound;
|
| 432 |
|
|
int stride;
|
| 433 |
|
|
} qualifiers[7];
|
| 434 |
|
|
|
| 435 |
|
|
bt_t basic_type;
|
| 436 |
|
|
int i;
|
| 437 |
|
|
static char buffer1[1024];
|
| 438 |
|
|
static char buffer2[1024];
|
| 439 |
|
|
char *p1 = buffer1;
|
| 440 |
|
|
char *p2 = buffer2;
|
| 441 |
|
|
char *used_ptr = aux_used + (aux_ptr - aux_symbols);
|
| 442 |
|
|
|
| 443 |
|
|
for (i = 0; i < 7; i++)
|
| 444 |
|
|
{
|
| 445 |
|
|
qualifiers[i].low_bound = 0;
|
| 446 |
|
|
qualifiers[i].high_bound = 0;
|
| 447 |
|
|
qualifiers[i].stride = 0;
|
| 448 |
|
|
}
|
| 449 |
|
|
|
| 450 |
|
|
used_ptr[index] = 1;
|
| 451 |
|
|
u = aux_ptr[index++];
|
| 452 |
|
|
if (u.isym == -1)
|
| 453 |
|
|
return "-1 (no type)";
|
| 454 |
|
|
|
| 455 |
|
|
basic_type = (bt_t) u.ti.bt;
|
| 456 |
|
|
qualifiers[0].type = (tq_t) u.ti.tq0;
|
| 457 |
|
|
qualifiers[1].type = (tq_t) u.ti.tq1;
|
| 458 |
|
|
qualifiers[2].type = (tq_t) u.ti.tq2;
|
| 459 |
|
|
qualifiers[3].type = (tq_t) u.ti.tq3;
|
| 460 |
|
|
qualifiers[4].type = (tq_t) u.ti.tq4;
|
| 461 |
|
|
qualifiers[5].type = (tq_t) u.ti.tq5;
|
| 462 |
|
|
qualifiers[6].type = tq_Nil;
|
| 463 |
|
|
|
| 464 |
|
|
/*
|
| 465 |
|
|
* Go get the basic type.
|
| 466 |
|
|
*/
|
| 467 |
|
|
switch (basic_type)
|
| 468 |
|
|
{
|
| 469 |
|
|
case bt_Nil: /* undefined */
|
| 470 |
|
|
strcpy (p1, "nil");
|
| 471 |
|
|
break;
|
| 472 |
|
|
|
| 473 |
|
|
case bt_Adr: /* address - integer same size as pointer */
|
| 474 |
|
|
strcpy (p1, "address");
|
| 475 |
|
|
break;
|
| 476 |
|
|
|
| 477 |
|
|
case bt_Char: /* character */
|
| 478 |
|
|
strcpy (p1, "char");
|
| 479 |
|
|
break;
|
| 480 |
|
|
|
| 481 |
|
|
case bt_UChar: /* unsigned character */
|
| 482 |
|
|
strcpy (p1, "unsigned char");
|
| 483 |
|
|
break;
|
| 484 |
|
|
|
| 485 |
|
|
case bt_Short: /* short */
|
| 486 |
|
|
strcpy (p1, "short");
|
| 487 |
|
|
break;
|
| 488 |
|
|
|
| 489 |
|
|
case bt_UShort: /* unsigned short */
|
| 490 |
|
|
strcpy (p1, "unsigned short");
|
| 491 |
|
|
break;
|
| 492 |
|
|
|
| 493 |
|
|
case bt_Int: /* int */
|
| 494 |
|
|
strcpy (p1, "int");
|
| 495 |
|
|
break;
|
| 496 |
|
|
|
| 497 |
|
|
case bt_UInt: /* unsigned int */
|
| 498 |
|
|
strcpy (p1, "unsigned int");
|
| 499 |
|
|
break;
|
| 500 |
|
|
|
| 501 |
|
|
case bt_Long: /* long */
|
| 502 |
|
|
strcpy (p1, "long");
|
| 503 |
|
|
break;
|
| 504 |
|
|
|
| 505 |
|
|
case bt_ULong: /* unsigned long */
|
| 506 |
|
|
strcpy (p1, "unsigned long");
|
| 507 |
|
|
break;
|
| 508 |
|
|
|
| 509 |
|
|
case bt_Float: /* float (real) */
|
| 510 |
|
|
strcpy (p1, "float");
|
| 511 |
|
|
break;
|
| 512 |
|
|
|
| 513 |
|
|
case bt_Double: /* Double (real) */
|
| 514 |
|
|
strcpy (p1, "double");
|
| 515 |
|
|
break;
|
| 516 |
|
|
|
| 517 |
|
|
/* Structures add 1-2 aux words:
|
| 518 |
|
|
1st word is [ST_RFDESCAPE, offset] pointer to struct def;
|
| 519 |
|
|
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
|
| 520 |
|
|
|
| 521 |
|
|
case bt_Struct: /* Structure (Record) */
|
| 522 |
|
|
emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp);
|
| 523 |
|
|
used_ptr[index] = 1;
|
| 524 |
|
|
if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
|
| 525 |
|
|
used_ptr[++index] = 1;
|
| 526 |
|
|
|
| 527 |
|
|
index++; /* skip aux words */
|
| 528 |
|
|
break;
|
| 529 |
|
|
|
| 530 |
|
|
/* Unions add 1-2 aux words:
|
| 531 |
|
|
1st word is [ST_RFDESCAPE, offset] pointer to union def;
|
| 532 |
|
|
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
|
| 533 |
|
|
|
| 534 |
|
|
case bt_Union: /* Union */
|
| 535 |
|
|
emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp);
|
| 536 |
|
|
used_ptr[index] = 1;
|
| 537 |
|
|
if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
|
| 538 |
|
|
used_ptr[++index] = 1;
|
| 539 |
|
|
|
| 540 |
|
|
index++; /* skip aux words */
|
| 541 |
|
|
break;
|
| 542 |
|
|
|
| 543 |
|
|
/* Enumerations add 1-2 aux words:
|
| 544 |
|
|
1st word is [ST_RFDESCAPE, offset] pointer to enum def;
|
| 545 |
|
|
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
|
| 546 |
|
|
|
| 547 |
|
|
case bt_Enum: /* Enumeration */
|
| 548 |
|
|
emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp);
|
| 549 |
|
|
used_ptr[index] = 1;
|
| 550 |
|
|
if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
|
| 551 |
|
|
used_ptr[++index] = 1;
|
| 552 |
|
|
|
| 553 |
|
|
index++; /* skip aux words */
|
| 554 |
|
|
break;
|
| 555 |
|
|
|
| 556 |
|
|
case bt_Typedef: /* defined via a typedef, isymRef points */
|
| 557 |
|
|
strcpy (p1, "typedef");
|
| 558 |
|
|
break;
|
| 559 |
|
|
|
| 560 |
|
|
case bt_Range: /* subrange of int */
|
| 561 |
|
|
strcpy (p1, "subrange");
|
| 562 |
|
|
break;
|
| 563 |
|
|
|
| 564 |
|
|
case bt_Set: /* pascal sets */
|
| 565 |
|
|
strcpy (p1, "set");
|
| 566 |
|
|
break;
|
| 567 |
|
|
|
| 568 |
|
|
case bt_Complex: /* fortran complex */
|
| 569 |
|
|
strcpy (p1, "complex");
|
| 570 |
|
|
break;
|
| 571 |
|
|
|
| 572 |
|
|
case bt_DComplex: /* fortran double complex */
|
| 573 |
|
|
strcpy (p1, "double complex");
|
| 574 |
|
|
break;
|
| 575 |
|
|
|
| 576 |
|
|
case bt_Indirect: /* forward or unnamed typedef */
|
| 577 |
|
|
strcpy (p1, "forward/unnamed typedef");
|
| 578 |
|
|
break;
|
| 579 |
|
|
|
| 580 |
|
|
case bt_FixedDec: /* Fixed Decimal */
|
| 581 |
|
|
strcpy (p1, "fixed decimal");
|
| 582 |
|
|
break;
|
| 583 |
|
|
|
| 584 |
|
|
case bt_FloatDec: /* Float Decimal */
|
| 585 |
|
|
strcpy (p1, "float decimal");
|
| 586 |
|
|
break;
|
| 587 |
|
|
|
| 588 |
|
|
case bt_String: /* Varying Length Character String */
|
| 589 |
|
|
strcpy (p1, "string");
|
| 590 |
|
|
break;
|
| 591 |
|
|
|
| 592 |
|
|
case bt_Bit: /* Aligned Bit String */
|
| 593 |
|
|
strcpy (p1, "bit");
|
| 594 |
|
|
break;
|
| 595 |
|
|
|
| 596 |
|
|
case bt_Picture: /* Picture */
|
| 597 |
|
|
strcpy (p1, "picture");
|
| 598 |
|
|
break;
|
| 599 |
|
|
|
| 600 |
|
|
case bt_Void: /* Void */
|
| 601 |
|
|
strcpy (p1, "void");
|
| 602 |
|
|
break;
|
| 603 |
|
|
|
| 604 |
|
|
default:
|
| 605 |
|
|
sprintf (p1, "Unknown basic type %d", (int) basic_type);
|
| 606 |
|
|
break;
|
| 607 |
|
|
}
|
| 608 |
|
|
|
| 609 |
|
|
p1 += strlen (buffer1);
|
| 610 |
|
|
|
| 611 |
|
|
/*
|
| 612 |
|
|
* If this is a bitfield, get the bitsize.
|
| 613 |
|
|
*/
|
| 614 |
|
|
if (u.ti.fBitfield)
|
| 615 |
|
|
{
|
| 616 |
|
|
int bitsize;
|
| 617 |
|
|
|
| 618 |
|
|
used_ptr[index] = 1;
|
| 619 |
|
|
bitsize = aux_ptr[index++].width;
|
| 620 |
|
|
sprintf (p1, " : %d", bitsize);
|
| 621 |
|
|
p1 += strlen (buffer1);
|
| 622 |
|
|
}
|
| 623 |
|
|
|
| 624 |
|
|
|
| 625 |
|
|
/*
|
| 626 |
|
|
* Deal with any qualifiers.
|
| 627 |
|
|
*/
|
| 628 |
|
|
if (qualifiers[0].type != tq_Nil)
|
| 629 |
|
|
{
|
| 630 |
|
|
/*
|
| 631 |
|
|
* Snarf up any array bounds in the correct order. Arrays
|
| 632 |
|
|
* store 5 successive words in the aux. table:
|
| 633 |
|
|
* word 0 RNDXR to type of the bounds (i.e., int)
|
| 634 |
|
|
* word 1 Current file descriptor index
|
| 635 |
|
|
* word 2 low bound
|
| 636 |
|
|
* word 3 high bound (or -1 if [])
|
| 637 |
|
|
* word 4 stride size in bits
|
| 638 |
|
|
*/
|
| 639 |
|
|
for (i = 0; i < 7; i++)
|
| 640 |
|
|
{
|
| 641 |
|
|
if (qualifiers[i].type == tq_Array)
|
| 642 |
|
|
{
|
| 643 |
|
|
qualifiers[i].low_bound = aux_ptr[index+2].dnLow;
|
| 644 |
|
|
qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
|
| 645 |
|
|
qualifiers[i].stride = aux_ptr[index+4].width;
|
| 646 |
|
|
used_ptr[index] = 1;
|
| 647 |
|
|
used_ptr[index+1] = 1;
|
| 648 |
|
|
used_ptr[index+2] = 1;
|
| 649 |
|
|
used_ptr[index+3] = 1;
|
| 650 |
|
|
used_ptr[index+4] = 1;
|
| 651 |
|
|
index += 5;
|
| 652 |
|
|
}
|
| 653 |
|
|
}
|
| 654 |
|
|
|
| 655 |
|
|
/*
|
| 656 |
|
|
* Now print out the qualifiers.
|
| 657 |
|
|
*/
|
| 658 |
|
|
for (i = 0; i < 6; i++)
|
| 659 |
|
|
{
|
| 660 |
|
|
switch (qualifiers[i].type)
|
| 661 |
|
|
{
|
| 662 |
|
|
case tq_Nil:
|
| 663 |
|
|
case tq_Max:
|
| 664 |
|
|
break;
|
| 665 |
|
|
|
| 666 |
|
|
case tq_Ptr:
|
| 667 |
|
|
strcpy (p2, "ptr to ");
|
| 668 |
|
|
p2 += sizeof ("ptr to ")-1;
|
| 669 |
|
|
break;
|
| 670 |
|
|
|
| 671 |
|
|
case tq_Vol:
|
| 672 |
|
|
strcpy (p2, "volatile ");
|
| 673 |
|
|
p2 += sizeof ("volatile ")-1;
|
| 674 |
|
|
break;
|
| 675 |
|
|
|
| 676 |
|
|
case tq_Far:
|
| 677 |
|
|
strcpy (p2, "far ");
|
| 678 |
|
|
p2 += sizeof ("far ")-1;
|
| 679 |
|
|
break;
|
| 680 |
|
|
|
| 681 |
|
|
case tq_Proc:
|
| 682 |
|
|
strcpy (p2, "func. ret. ");
|
| 683 |
|
|
p2 += sizeof ("func. ret. ");
|
| 684 |
|
|
break;
|
| 685 |
|
|
|
| 686 |
|
|
case tq_Array:
|
| 687 |
|
|
{
|
| 688 |
|
|
int first_array = i;
|
| 689 |
|
|
int j;
|
| 690 |
|
|
|
| 691 |
|
|
/* Print array bounds reversed (i.e., in the order the C
|
| 692 |
|
|
programmer writes them). C is such a fun language.... */
|
| 693 |
|
|
|
| 694 |
|
|
while (i < 5 && qualifiers[i+1].type == tq_Array)
|
| 695 |
|
|
i++;
|
| 696 |
|
|
|
| 697 |
|
|
for (j = i; j >= first_array; j--)
|
| 698 |
|
|
{
|
| 699 |
|
|
strcpy (p2, "array [");
|
| 700 |
|
|
p2 += sizeof ("array [")-1;
|
| 701 |
|
|
if (qualifiers[j].low_bound != 0)
|
| 702 |
|
|
sprintf (p2,
|
| 703 |
|
|
"%ld:%ld {%ld bits}",
|
| 704 |
|
|
(long) qualifiers[j].low_bound,
|
| 705 |
|
|
(long) qualifiers[j].high_bound,
|
| 706 |
|
|
(long) qualifiers[j].stride);
|
| 707 |
|
|
|
| 708 |
|
|
else if (qualifiers[j].high_bound != -1)
|
| 709 |
|
|
sprintf (p2,
|
| 710 |
|
|
"%ld {%ld bits}",
|
| 711 |
|
|
(long) (qualifiers[j].high_bound + 1),
|
| 712 |
|
|
(long) (qualifiers[j].stride));
|
| 713 |
|
|
|
| 714 |
|
|
else
|
| 715 |
|
|
sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
|
| 716 |
|
|
|
| 717 |
|
|
p2 += strlen (p2);
|
| 718 |
|
|
strcpy (p2, "] of ");
|
| 719 |
|
|
p2 += sizeof ("] of ")-1;
|
| 720 |
|
|
}
|
| 721 |
|
|
}
|
| 722 |
|
|
break;
|
| 723 |
|
|
}
|
| 724 |
|
|
}
|
| 725 |
|
|
}
|
| 726 |
|
|
|
| 727 |
|
|
strcpy (p2, buffer1);
|
| 728 |
|
|
return buffer2;
|
| 729 |
|
|
}
|
| 730 |
|
|
|
| 731 |
|
|
|
| 732 |
|
|
/* Print out the global file header for object files. */
|
| 733 |
|
|
|
| 734 |
|
|
static void
|
| 735 |
|
|
print_global_hdr (struct filehdr *ptr)
|
| 736 |
|
|
{
|
| 737 |
|
|
char *time = ctime ((time_t *)&ptr->f_timdat);
|
| 738 |
|
|
ushort flags = ptr->f_flags;
|
| 739 |
|
|
|
| 740 |
|
|
printf("Global file header:\n");
|
| 741 |
|
|
printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic);
|
| 742 |
|
|
printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns);
|
| 743 |
|
|
printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time);
|
| 744 |
|
|
printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr);
|
| 745 |
|
|
printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms);
|
| 746 |
|
|
printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr);
|
| 747 |
|
|
printf(" %-*s 0x%x", 24, "flags", (ushort) flags);
|
| 748 |
|
|
|
| 749 |
|
|
if ((flags & F_RELFLG) != 0)
|
| 750 |
|
|
printf (", F_RELFLG");
|
| 751 |
|
|
|
| 752 |
|
|
if ((flags & F_EXEC) != 0)
|
| 753 |
|
|
printf (", F_EXEC");
|
| 754 |
|
|
|
| 755 |
|
|
if ((flags & F_LNNO) != 0)
|
| 756 |
|
|
printf (", F_LNNO");
|
| 757 |
|
|
|
| 758 |
|
|
if ((flags & F_LSYMS) != 0)
|
| 759 |
|
|
printf (", F_LSYMS");
|
| 760 |
|
|
|
| 761 |
|
|
if ((flags & F_MINMAL) != 0)
|
| 762 |
|
|
printf (", F_MINMAL");
|
| 763 |
|
|
|
| 764 |
|
|
if ((flags & F_UPDATE) != 0)
|
| 765 |
|
|
printf (", F_UPDATE");
|
| 766 |
|
|
|
| 767 |
|
|
if ((flags & F_SWABD) != 0)
|
| 768 |
|
|
printf (", F_SWABD");
|
| 769 |
|
|
|
| 770 |
|
|
if ((flags & F_AR16WR) != 0)
|
| 771 |
|
|
printf (", F_AR16WR");
|
| 772 |
|
|
|
| 773 |
|
|
if ((flags & F_AR32WR) != 0)
|
| 774 |
|
|
printf (", F_AR32WR");
|
| 775 |
|
|
|
| 776 |
|
|
if ((flags & F_AR32W) != 0)
|
| 777 |
|
|
printf (", F_AR32W");
|
| 778 |
|
|
|
| 779 |
|
|
if ((flags & F_PATCH) != 0)
|
| 780 |
|
|
printf (", F_PATCH/F_NODF");
|
| 781 |
|
|
|
| 782 |
|
|
printf ("\n\n");
|
| 783 |
|
|
}
|
| 784 |
|
|
|
| 785 |
|
|
|
| 786 |
|
|
/* Print out the symbolic header. */
|
| 787 |
|
|
|
| 788 |
|
|
static void
|
| 789 |
|
|
print_sym_hdr (HDRR *sym_ptr)
|
| 790 |
|
|
{
|
| 791 |
|
|
int width = 20;
|
| 792 |
|
|
|
| 793 |
|
|
printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
|
| 794 |
|
|
sym_ptr->magic & 0xffff,
|
| 795 |
|
|
(sym_ptr->vstamp & 0xffff) >> 8,
|
| 796 |
|
|
sym_ptr->vstamp & 0xff);
|
| 797 |
|
|
|
| 798 |
|
|
printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
|
| 799 |
|
|
printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
|
| 800 |
|
|
|
| 801 |
|
|
printf(" %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
|
| 802 |
|
|
(long) sym_ptr->cbLineOffset,
|
| 803 |
|
|
(long) sym_ptr->cbLine,
|
| 804 |
|
|
(long) sym_ptr->cbLine,
|
| 805 |
|
|
(int) sym_ptr->ilineMax);
|
| 806 |
|
|
|
| 807 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
|
| 808 |
|
|
(long) sym_ptr->cbDnOffset,
|
| 809 |
|
|
(long) sym_ptr->idnMax,
|
| 810 |
|
|
(long) (sym_ptr->idnMax * sizeof (DNR)));
|
| 811 |
|
|
|
| 812 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
|
| 813 |
|
|
(long) sym_ptr->cbPdOffset,
|
| 814 |
|
|
(long) sym_ptr->ipdMax,
|
| 815 |
|
|
(long) (sym_ptr->ipdMax * sizeof (PDR)));
|
| 816 |
|
|
|
| 817 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
|
| 818 |
|
|
(long) sym_ptr->cbSymOffset,
|
| 819 |
|
|
(long) sym_ptr->isymMax,
|
| 820 |
|
|
(long) (sym_ptr->isymMax * sizeof (SYMR)));
|
| 821 |
|
|
|
| 822 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
|
| 823 |
|
|
(long) sym_ptr->cbOptOffset,
|
| 824 |
|
|
(long) sym_ptr->ioptMax,
|
| 825 |
|
|
(long) (sym_ptr->ioptMax * sizeof (OPTR)));
|
| 826 |
|
|
|
| 827 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
|
| 828 |
|
|
(long) sym_ptr->cbAuxOffset,
|
| 829 |
|
|
(long) sym_ptr->iauxMax,
|
| 830 |
|
|
(long) (sym_ptr->iauxMax * sizeof (AUXU)));
|
| 831 |
|
|
|
| 832 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Local Strings",
|
| 833 |
|
|
(long) sym_ptr->cbSsOffset,
|
| 834 |
|
|
(long) sym_ptr->issMax,
|
| 835 |
|
|
(long) sym_ptr->issMax);
|
| 836 |
|
|
|
| 837 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "External Strings",
|
| 838 |
|
|
(long) sym_ptr->cbSsExtOffset,
|
| 839 |
|
|
(long) sym_ptr->issExtMax,
|
| 840 |
|
|
(long) sym_ptr->issExtMax);
|
| 841 |
|
|
|
| 842 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "File Tables",
|
| 843 |
|
|
(long) sym_ptr->cbFdOffset,
|
| 844 |
|
|
(long) sym_ptr->ifdMax,
|
| 845 |
|
|
(long) (sym_ptr->ifdMax * sizeof (FDR)));
|
| 846 |
|
|
|
| 847 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "Relative Files",
|
| 848 |
|
|
(long) sym_ptr->cbRfdOffset,
|
| 849 |
|
|
(long) sym_ptr->crfd,
|
| 850 |
|
|
(long) (sym_ptr->crfd * sizeof (ulong)));
|
| 851 |
|
|
|
| 852 |
|
|
printf(" %-*s %11ld %11ld %11ld\n", width, "External Symbols",
|
| 853 |
|
|
(long) sym_ptr->cbExtOffset,
|
| 854 |
|
|
(long) sym_ptr->iextMax,
|
| 855 |
|
|
(long) (sym_ptr->iextMax * sizeof (EXTR)));
|
| 856 |
|
|
}
|
| 857 |
|
|
|
| 858 |
|
|
|
| 859 |
|
|
/* Print out a symbol. */
|
| 860 |
|
|
|
| 861 |
|
|
static void
|
| 862 |
|
|
print_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base,
|
| 863 |
|
|
int ifd, FDR *fdp)
|
| 864 |
|
|
{
|
| 865 |
|
|
sc_t storage_class = (sc_t) sym_ptr->sc;
|
| 866 |
|
|
st_t symbol_type = (st_t) sym_ptr->st;
|
| 867 |
|
|
ulong index = sym_ptr->index;
|
| 868 |
|
|
char *used_ptr = aux_used + (aux_base - aux_symbols);
|
| 869 |
|
|
scope_t *scope_ptr;
|
| 870 |
|
|
|
| 871 |
|
|
printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
|
| 872 |
|
|
|
| 873 |
|
|
if (aux_base != (AUXU *) 0 && index != indexNil)
|
| 874 |
|
|
switch (symbol_type)
|
| 875 |
|
|
{
|
| 876 |
|
|
case st_Nil:
|
| 877 |
|
|
case st_Label:
|
| 878 |
|
|
break;
|
| 879 |
|
|
|
| 880 |
|
|
case st_File:
|
| 881 |
|
|
case st_Block:
|
| 882 |
|
|
printf (" End+1 symbol: %ld\n", index);
|
| 883 |
|
|
if (want_scope)
|
| 884 |
|
|
{
|
| 885 |
|
|
if (free_scope == (scope_t *) 0)
|
| 886 |
|
|
scope_ptr = (scope_t *) xmalloc (sizeof (scope_t));
|
| 887 |
|
|
else
|
| 888 |
|
|
{
|
| 889 |
|
|
scope_ptr = free_scope;
|
| 890 |
|
|
free_scope = scope_ptr->prev;
|
| 891 |
|
|
}
|
| 892 |
|
|
scope_ptr->open_sym = number;
|
| 893 |
|
|
scope_ptr->st = symbol_type;
|
| 894 |
|
|
scope_ptr->sc = storage_class;
|
| 895 |
|
|
scope_ptr->prev = cur_scope;
|
| 896 |
|
|
cur_scope = scope_ptr;
|
| 897 |
|
|
}
|
| 898 |
|
|
break;
|
| 899 |
|
|
|
| 900 |
|
|
case st_End:
|
| 901 |
|
|
if (storage_class == sc_Text || storage_class == sc_Info)
|
| 902 |
|
|
printf (" First symbol: %ld\n", index);
|
| 903 |
|
|
else
|
| 904 |
|
|
{
|
| 905 |
|
|
used_ptr[index] = 1;
|
| 906 |
|
|
printf (" First symbol: %ld\n", (long) aux_base[index].isym);
|
| 907 |
|
|
}
|
| 908 |
|
|
|
| 909 |
|
|
if (want_scope)
|
| 910 |
|
|
{
|
| 911 |
|
|
if (cur_scope == (scope_t *) 0)
|
| 912 |
|
|
printf (" Can't pop end scope\n");
|
| 913 |
|
|
else
|
| 914 |
|
|
{
|
| 915 |
|
|
scope_ptr = cur_scope;
|
| 916 |
|
|
cur_scope = scope_ptr->prev;
|
| 917 |
|
|
scope_ptr->prev = free_scope;
|
| 918 |
|
|
free_scope = scope_ptr;
|
| 919 |
|
|
}
|
| 920 |
|
|
}
|
| 921 |
|
|
break;
|
| 922 |
|
|
|
| 923 |
|
|
case st_Proc:
|
| 924 |
|
|
case st_StaticProc:
|
| 925 |
|
|
if (MIPS_IS_STAB(sym_ptr))
|
| 926 |
|
|
;
|
| 927 |
|
|
else if (ifd == -1) /* local symbol */
|
| 928 |
|
|
{
|
| 929 |
|
|
used_ptr[index] = used_ptr[index+1] = 1;
|
| 930 |
|
|
printf (" End+1 symbol: %-7ld Type: %s\n",
|
| 931 |
|
|
(long) aux_base[index].isym,
|
| 932 |
|
|
type_to_string (aux_base, index+1, fdp));
|
| 933 |
|
|
}
|
| 934 |
|
|
else /* global symbol */
|
| 935 |
|
|
printf (" Local symbol: %ld\n", index);
|
| 936 |
|
|
|
| 937 |
|
|
if (want_scope)
|
| 938 |
|
|
{
|
| 939 |
|
|
if (free_scope == (scope_t *) 0)
|
| 940 |
|
|
scope_ptr = (scope_t *) xmalloc (sizeof (scope_t));
|
| 941 |
|
|
else
|
| 942 |
|
|
{
|
| 943 |
|
|
scope_ptr = free_scope;
|
| 944 |
|
|
free_scope = scope_ptr->prev;
|
| 945 |
|
|
}
|
| 946 |
|
|
scope_ptr->open_sym = number;
|
| 947 |
|
|
scope_ptr->st = symbol_type;
|
| 948 |
|
|
scope_ptr->sc = storage_class;
|
| 949 |
|
|
scope_ptr->prev = cur_scope;
|
| 950 |
|
|
cur_scope = scope_ptr;
|
| 951 |
|
|
}
|
| 952 |
|
|
break;
|
| 953 |
|
|
|
| 954 |
|
|
#ifdef stStruct
|
| 955 |
|
|
case st_Struct:
|
| 956 |
|
|
case st_Union:
|
| 957 |
|
|
case st_Enum:
|
| 958 |
|
|
printf (" End+1 symbol: %lu\n", index);
|
| 959 |
|
|
break;
|
| 960 |
|
|
#endif
|
| 961 |
|
|
|
| 962 |
|
|
default:
|
| 963 |
|
|
if (!MIPS_IS_STAB (sym_ptr))
|
| 964 |
|
|
{
|
| 965 |
|
|
used_ptr[index] = 1;
|
| 966 |
|
|
printf (" Type: %s\n",
|
| 967 |
|
|
type_to_string (aux_base, index, fdp));
|
| 968 |
|
|
}
|
| 969 |
|
|
break;
|
| 970 |
|
|
}
|
| 971 |
|
|
|
| 972 |
|
|
if (want_scope)
|
| 973 |
|
|
{
|
| 974 |
|
|
printf (" Scopes: ");
|
| 975 |
|
|
if (cur_scope == (scope_t *) 0)
|
| 976 |
|
|
printf (" none\n");
|
| 977 |
|
|
else
|
| 978 |
|
|
{
|
| 979 |
|
|
for (scope_ptr = cur_scope;
|
| 980 |
|
|
scope_ptr != (scope_t *) 0;
|
| 981 |
|
|
scope_ptr = scope_ptr->prev)
|
| 982 |
|
|
{
|
| 983 |
|
|
const char *sclass;
|
| 984 |
|
|
if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
|
| 985 |
|
|
sclass = "func.";
|
| 986 |
|
|
else if (scope_ptr->st == st_File)
|
| 987 |
|
|
sclass = "file";
|
| 988 |
|
|
else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
|
| 989 |
|
|
sclass = "block";
|
| 990 |
|
|
else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
|
| 991 |
|
|
sclass = "type";
|
| 992 |
|
|
else
|
| 993 |
|
|
sclass = "???";
|
| 994 |
|
|
|
| 995 |
|
|
printf (" %ld [%s]", scope_ptr->open_sym, sclass);
|
| 996 |
|
|
}
|
| 997 |
|
|
printf ("\n");
|
| 998 |
|
|
}
|
| 999 |
|
|
}
|
| 1000 |
|
|
|
| 1001 |
|
|
printf (" Value: %-13ld ",
|
| 1002 |
|
|
(long)sym_ptr->value);
|
| 1003 |
|
|
if (ifd == -1)
|
| 1004 |
|
|
printf ("String index: %ld\n", (long)sym_ptr->iss);
|
| 1005 |
|
|
else
|
| 1006 |
|
|
printf ("String index: %-11ld Ifd: %d\n",
|
| 1007 |
|
|
(long)sym_ptr->iss, ifd);
|
| 1008 |
|
|
|
| 1009 |
|
|
printf (" Symbol type: %-11sStorage class: %-11s",
|
| 1010 |
|
|
st_to_string (symbol_type), sc_to_string (storage_class));
|
| 1011 |
|
|
|
| 1012 |
|
|
if (MIPS_IS_STAB(sym_ptr))
|
| 1013 |
|
|
{
|
| 1014 |
|
|
int i = ARRAY_SIZE (stab_names);
|
| 1015 |
|
|
const char *stab_name = "stab";
|
| 1016 |
|
|
short code = MIPS_UNMARK_STAB(sym_ptr->index);
|
| 1017 |
|
|
|
| 1018 |
|
|
while (--i >= 0)
|
| 1019 |
|
|
if (stab_names[i].code == code)
|
| 1020 |
|
|
{
|
| 1021 |
|
|
stab_name = stab_names[i].string;
|
| 1022 |
|
|
break;
|
| 1023 |
|
|
}
|
| 1024 |
|
|
printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
|
| 1025 |
|
|
}
|
| 1026 |
|
|
else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
|
| 1027 |
|
|
printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
|
| 1028 |
|
|
else
|
| 1029 |
|
|
printf ("Index: %ld\n", (long)sym_ptr->index);
|
| 1030 |
|
|
|
| 1031 |
|
|
}
|
| 1032 |
|
|
|
| 1033 |
|
|
|
| 1034 |
|
|
/* Print out a word from the aux. table in various formats. */
|
| 1035 |
|
|
|
| 1036 |
|
|
static void
|
| 1037 |
|
|
print_aux (AUXU u, int auxi, int used)
|
| 1038 |
|
|
{
|
| 1039 |
|
|
printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
|
| 1040 |
|
|
(used) ? " " : "* ",
|
| 1041 |
|
|
auxi,
|
| 1042 |
|
|
(long) u.isym,
|
| 1043 |
|
|
(long) u.rndx.rfd,
|
| 1044 |
|
|
(long) u.rndx.index,
|
| 1045 |
|
|
u.ti.bt,
|
| 1046 |
|
|
u.ti.fBitfield,
|
| 1047 |
|
|
u.ti.continued,
|
| 1048 |
|
|
u.ti.tq0,
|
| 1049 |
|
|
u.ti.tq1,
|
| 1050 |
|
|
u.ti.tq2,
|
| 1051 |
|
|
u.ti.tq3,
|
| 1052 |
|
|
u.ti.tq4,
|
| 1053 |
|
|
u.ti.tq5);
|
| 1054 |
|
|
}
|
| 1055 |
|
|
|
| 1056 |
|
|
|
| 1057 |
|
|
/* Write aggregate information to a string. */
|
| 1058 |
|
|
|
| 1059 |
|
|
static void
|
| 1060 |
|
|
emit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp)
|
| 1061 |
|
|
{
|
| 1062 |
|
|
unsigned int ifd = u.rndx.rfd;
|
| 1063 |
|
|
unsigned int index = u.rndx.index;
|
| 1064 |
|
|
const char *name;
|
| 1065 |
|
|
|
| 1066 |
|
|
if (ifd == ST_RFDESCAPE)
|
| 1067 |
|
|
ifd = u2.isym;
|
| 1068 |
|
|
|
| 1069 |
|
|
/* An ifd of -1 is an opaque type. An escaped index of 0 is a
|
| 1070 |
|
|
struct return type of a procedure compiled without -g. */
|
| 1071 |
|
|
if (ifd == 0xffffffff
|
| 1072 |
|
|
|| (u.rndx.rfd == ST_RFDESCAPE && index == 0))
|
| 1073 |
|
|
name = "<undefined>";
|
| 1074 |
|
|
else if (index == indexNil)
|
| 1075 |
|
|
name = "<no name>";
|
| 1076 |
|
|
else
|
| 1077 |
|
|
{
|
| 1078 |
|
|
if (fdp == 0 || sym_hdr.crfd == 0)
|
| 1079 |
|
|
fdp = &file_desc[ifd];
|
| 1080 |
|
|
else
|
| 1081 |
|
|
fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]];
|
| 1082 |
|
|
name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss];
|
| 1083 |
|
|
}
|
| 1084 |
|
|
|
| 1085 |
|
|
sprintf (string,
|
| 1086 |
|
|
"%s %s { ifd = %u, index = %u }",
|
| 1087 |
|
|
which, name, ifd, index);
|
| 1088 |
|
|
}
|
| 1089 |
|
|
|
| 1090 |
|
|
|
| 1091 |
|
|
/* Print out information about a file descriptor, and the symbols,
|
| 1092 |
|
|
procedures, and line numbers within it. */
|
| 1093 |
|
|
|
| 1094 |
|
|
static void
|
| 1095 |
|
|
print_file_desc (FDR *fdp, int number)
|
| 1096 |
|
|
{
|
| 1097 |
|
|
char *str_base;
|
| 1098 |
|
|
AUXU *aux_base;
|
| 1099 |
|
|
int symi, pdi;
|
| 1100 |
|
|
int width = 20;
|
| 1101 |
|
|
char *used_base;
|
| 1102 |
|
|
|
| 1103 |
|
|
str_base = l_strings + fdp->issBase;
|
| 1104 |
|
|
aux_base = aux_symbols + fdp->iauxBase;
|
| 1105 |
|
|
used_base = aux_used + (aux_base - aux_symbols);
|
| 1106 |
|
|
|
| 1107 |
|
|
printf ("\nFile #%d, \"%s\"\n\n",
|
| 1108 |
|
|
number,
|
| 1109 |
|
|
fdp->rss != issNil ? str_base + fdp->rss : "<unknown>");
|
| 1110 |
|
|
|
| 1111 |
|
|
printf (" Name index = %-10ld Readin = %s\n",
|
| 1112 |
|
|
(long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
|
| 1113 |
|
|
|
| 1114 |
|
|
printf (" Merge = %-10s Endian = %s\n",
|
| 1115 |
|
|
(fdp->fMerge) ? "Yes" : "No",
|
| 1116 |
|
|
(fdp->fBigendian) ? "BIG" : "LITTLE");
|
| 1117 |
|
|
|
| 1118 |
|
|
printf (" Debug level = %-10s Language = %s\n",
|
| 1119 |
|
|
glevel_to_string ((glevel_t) fdp->glevel),
|
| 1120 |
|
|
lang_to_string((lang_t) fdp->lang));
|
| 1121 |
|
|
|
| 1122 |
|
|
printf (" Adr = 0x%08lx\n\n", (long) fdp->adr);
|
| 1123 |
|
|
|
| 1124 |
|
|
printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
|
| 1125 |
|
|
printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
|
| 1126 |
|
|
|
| 1127 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1128 |
|
|
width, "Local strings",
|
| 1129 |
|
|
(ulong) fdp->issBase,
|
| 1130 |
|
|
(ulong) fdp->cbSs,
|
| 1131 |
|
|
(ulong) fdp->cbSs,
|
| 1132 |
|
|
(ulong) (fdp->issBase + sym_hdr.cbSsOffset));
|
| 1133 |
|
|
|
| 1134 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1135 |
|
|
width, "Local symbols",
|
| 1136 |
|
|
(ulong) fdp->isymBase,
|
| 1137 |
|
|
(ulong) fdp->csym,
|
| 1138 |
|
|
(ulong) (fdp->csym * sizeof (SYMR)),
|
| 1139 |
|
|
(ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
|
| 1140 |
|
|
|
| 1141 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1142 |
|
|
width, "Line numbers",
|
| 1143 |
|
|
(ulong) fdp->cbLineOffset,
|
| 1144 |
|
|
(ulong) fdp->cline,
|
| 1145 |
|
|
(ulong) fdp->cbLine,
|
| 1146 |
|
|
(ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
|
| 1147 |
|
|
|
| 1148 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1149 |
|
|
width, "Optimization symbols",
|
| 1150 |
|
|
(ulong) fdp->ioptBase,
|
| 1151 |
|
|
(ulong) fdp->copt,
|
| 1152 |
|
|
(ulong) (fdp->copt * sizeof (OPTR)),
|
| 1153 |
|
|
(ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
|
| 1154 |
|
|
|
| 1155 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1156 |
|
|
width, "Procedures",
|
| 1157 |
|
|
(ulong) fdp->ipdFirst,
|
| 1158 |
|
|
(ulong) fdp->cpd,
|
| 1159 |
|
|
(ulong) (fdp->cpd * sizeof (PDR)),
|
| 1160 |
|
|
(ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
|
| 1161 |
|
|
|
| 1162 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1163 |
|
|
width, "Auxiliary symbols",
|
| 1164 |
|
|
(ulong) fdp->iauxBase,
|
| 1165 |
|
|
(ulong) fdp->caux,
|
| 1166 |
|
|
(ulong) (fdp->caux * sizeof (AUXU)),
|
| 1167 |
|
|
(ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
|
| 1168 |
|
|
|
| 1169 |
|
|
printf(" %-*s %11lu %11lu %11lu %11lu\n",
|
| 1170 |
|
|
width, "Relative Files",
|
| 1171 |
|
|
(ulong) fdp->rfdBase,
|
| 1172 |
|
|
(ulong) fdp->crfd,
|
| 1173 |
|
|
(ulong) (fdp->crfd * sizeof (ulong)),
|
| 1174 |
|
|
(ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
|
| 1175 |
|
|
|
| 1176 |
|
|
|
| 1177 |
|
|
if (want_scope && cur_scope != (scope_t *) 0)
|
| 1178 |
|
|
printf ("\n Warning scope does not start at 0!\n");
|
| 1179 |
|
|
|
| 1180 |
|
|
/*
|
| 1181 |
|
|
* print the info about the symbol table.
|
| 1182 |
|
|
*/
|
| 1183 |
|
|
printf ("\n There are %lu local symbols, starting at %lu\n",
|
| 1184 |
|
|
(ulong) fdp->csym,
|
| 1185 |
|
|
(ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
|
| 1186 |
|
|
|
| 1187 |
|
|
for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
|
| 1188 |
|
|
print_symbol (&l_symbols[symi],
|
| 1189 |
|
|
symi - fdp->isymBase,
|
| 1190 |
|
|
str_base,
|
| 1191 |
|
|
aux_base,
|
| 1192 |
|
|
-1,
|
| 1193 |
|
|
fdp);
|
| 1194 |
|
|
|
| 1195 |
|
|
if (want_scope && cur_scope != (scope_t *) 0)
|
| 1196 |
|
|
printf ("\n Warning scope does not end at 0!\n");
|
| 1197 |
|
|
|
| 1198 |
|
|
/*
|
| 1199 |
|
|
* print the aux. table if desired.
|
| 1200 |
|
|
*/
|
| 1201 |
|
|
|
| 1202 |
|
|
if (want_aux && fdp->caux != 0)
|
| 1203 |
|
|
{
|
| 1204 |
|
|
int auxi;
|
| 1205 |
|
|
|
| 1206 |
|
|
printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n",
|
| 1207 |
|
|
(ulong) fdp->caux,
|
| 1208 |
|
|
(ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
|
| 1209 |
|
|
|
| 1210 |
|
|
for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
|
| 1211 |
|
|
print_aux (aux_base[auxi], auxi, used_base[auxi]);
|
| 1212 |
|
|
}
|
| 1213 |
|
|
|
| 1214 |
|
|
/*
|
| 1215 |
|
|
* print the relative file descriptors.
|
| 1216 |
|
|
*/
|
| 1217 |
|
|
if (want_rfd && fdp->crfd != 0)
|
| 1218 |
|
|
{
|
| 1219 |
|
|
ulong *rfd_ptr, i;
|
| 1220 |
|
|
|
| 1221 |
|
|
printf ("\n There are %lu relative file descriptors, starting at %lu.\n",
|
| 1222 |
|
|
(ulong) fdp->crfd,
|
| 1223 |
|
|
(ulong) fdp->rfdBase);
|
| 1224 |
|
|
|
| 1225 |
|
|
rfd_ptr = rfile_desc + fdp->rfdBase;
|
| 1226 |
|
|
for (i = 0; i < (ulong) fdp->crfd; i++)
|
| 1227 |
|
|
{
|
| 1228 |
|
|
printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
|
| 1229 |
|
|
rfd_ptr++;
|
| 1230 |
|
|
}
|
| 1231 |
|
|
}
|
| 1232 |
|
|
|
| 1233 |
|
|
/*
|
| 1234 |
|
|
* do the procedure descriptors.
|
| 1235 |
|
|
*/
|
| 1236 |
|
|
printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
|
| 1237 |
|
|
printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
|
| 1238 |
|
|
|
| 1239 |
|
|
for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
|
| 1240 |
|
|
{
|
| 1241 |
|
|
PDR *proc_ptr = &proc_desc[pdi];
|
| 1242 |
|
|
printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
|
| 1243 |
|
|
|
| 1244 |
|
|
if (l_symbols != 0)
|
| 1245 |
|
|
printf ("\t Name index = %-11ld Name = \"%s\"\n",
|
| 1246 |
|
|
(long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
|
| 1247 |
|
|
l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
|
| 1248 |
|
|
|
| 1249 |
|
|
printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
|
| 1250 |
|
|
(long) proc_ptr->regmask,
|
| 1251 |
|
|
(long) proc_ptr->regoffset,
|
| 1252 |
|
|
(long) proc_ptr->fregmask,
|
| 1253 |
|
|
(long) proc_ptr->fregoffset);
|
| 1254 |
|
|
|
| 1255 |
|
|
printf ("\t .frame $%d,%ld,$%d\n",
|
| 1256 |
|
|
(int) proc_ptr->framereg,
|
| 1257 |
|
|
(long) proc_ptr->frameoffset,
|
| 1258 |
|
|
(int) proc_ptr->pcreg);
|
| 1259 |
|
|
|
| 1260 |
|
|
printf ("\t Opt. start = %-11ld Symbols start = %ld\n",
|
| 1261 |
|
|
(long) proc_ptr->iopt,
|
| 1262 |
|
|
(long) proc_ptr->isym);
|
| 1263 |
|
|
|
| 1264 |
|
|
printf ("\t First line # = %-11ld Last line # = %ld\n",
|
| 1265 |
|
|
(long) proc_ptr->lnLow,
|
| 1266 |
|
|
(long) proc_ptr->lnHigh);
|
| 1267 |
|
|
|
| 1268 |
|
|
printf ("\t Line Offset = %-11ld Address = 0x%08lx\n",
|
| 1269 |
|
|
(long) proc_ptr->cbLineOffset,
|
| 1270 |
|
|
(long) proc_ptr->adr);
|
| 1271 |
|
|
|
| 1272 |
|
|
/*
|
| 1273 |
|
|
* print the line number entries.
|
| 1274 |
|
|
*/
|
| 1275 |
|
|
|
| 1276 |
|
|
if (want_line && fdp->cline != 0)
|
| 1277 |
|
|
{
|
| 1278 |
|
|
int delta, count;
|
| 1279 |
|
|
long cur_line = proc_ptr->lnLow;
|
| 1280 |
|
|
uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset
|
| 1281 |
|
|
+ fdp->cbLineOffset);
|
| 1282 |
|
|
uchar *line_end;
|
| 1283 |
|
|
|
| 1284 |
|
|
if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */
|
| 1285 |
|
|
line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
|
| 1286 |
|
|
else /* not last proc. */
|
| 1287 |
|
|
line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
|
| 1288 |
|
|
+ fdp->cbLineOffset);
|
| 1289 |
|
|
|
| 1290 |
|
|
printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
|
| 1291 |
|
|
(ulong) (line_end - line_ptr),
|
| 1292 |
|
|
(ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
|
| 1293 |
|
|
|
| 1294 |
|
|
while (line_ptr < line_end)
|
| 1295 |
|
|
{ /* sign extend nibble */
|
| 1296 |
|
|
delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
|
| 1297 |
|
|
count = (*line_ptr & 0xf) + 1;
|
| 1298 |
|
|
if (delta != -8)
|
| 1299 |
|
|
line_ptr++;
|
| 1300 |
|
|
else
|
| 1301 |
|
|
{
|
| 1302 |
|
|
delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
|
| 1303 |
|
|
delta = (delta ^ 0x8000) - 0x8000;
|
| 1304 |
|
|
line_ptr += 3;
|
| 1305 |
|
|
}
|
| 1306 |
|
|
|
| 1307 |
|
|
cur_line += delta;
|
| 1308 |
|
|
printf ("\t Line %11ld, delta %5d, count %2d\n",
|
| 1309 |
|
|
cur_line,
|
| 1310 |
|
|
delta,
|
| 1311 |
|
|
count);
|
| 1312 |
|
|
}
|
| 1313 |
|
|
}
|
| 1314 |
|
|
}
|
| 1315 |
|
|
}
|
| 1316 |
|
|
|
| 1317 |
|
|
|
| 1318 |
|
|
/* Read in the portions of the .T file that we will print out. */
|
| 1319 |
|
|
|
| 1320 |
|
|
static void
|
| 1321 |
|
|
read_tfile (void)
|
| 1322 |
|
|
{
|
| 1323 |
|
|
short magic;
|
| 1324 |
|
|
off_t sym_hdr_offset = 0;
|
| 1325 |
|
|
|
| 1326 |
|
|
read_seek (&magic, sizeof (magic), 0, "Magic number");
|
| 1327 |
|
|
if (!tfile)
|
| 1328 |
|
|
{
|
| 1329 |
|
|
/* Print out the global header, since this is not a T-file. */
|
| 1330 |
|
|
|
| 1331 |
|
|
read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header");
|
| 1332 |
|
|
|
| 1333 |
|
|
print_global_hdr (&global_hdr);
|
| 1334 |
|
|
|
| 1335 |
|
|
if (global_hdr.f_symptr == 0)
|
| 1336 |
|
|
{
|
| 1337 |
|
|
printf ("No symbolic header, Goodbye!\n");
|
| 1338 |
|
|
exit (1);
|
| 1339 |
|
|
}
|
| 1340 |
|
|
|
| 1341 |
|
|
sym_hdr_offset = global_hdr.f_symptr;
|
| 1342 |
|
|
}
|
| 1343 |
|
|
|
| 1344 |
|
|
read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header");
|
| 1345 |
|
|
|
| 1346 |
|
|
print_sym_hdr (&sym_hdr);
|
| 1347 |
|
|
|
| 1348 |
|
|
lines = (LINER *) read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset,
|
| 1349 |
|
|
"Line numbers");
|
| 1350 |
|
|
|
| 1351 |
|
|
dense_nums = (DNR *) read_seek (NULL, sym_hdr.idnMax * sizeof (DNR),
|
| 1352 |
|
|
sym_hdr.cbDnOffset, "Dense numbers");
|
| 1353 |
|
|
|
| 1354 |
|
|
proc_desc = (PDR *) read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR),
|
| 1355 |
|
|
sym_hdr.cbPdOffset, "Procedure tables");
|
| 1356 |
|
|
|
| 1357 |
|
|
l_symbols = (SYMR *) read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR),
|
| 1358 |
|
|
sym_hdr.cbSymOffset, "Local symbols");
|
| 1359 |
|
|
|
| 1360 |
|
|
opt_symbols = (OPTR *) read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR),
|
| 1361 |
|
|
sym_hdr.cbOptOffset,
|
| 1362 |
|
|
"Optimization symbols");
|
| 1363 |
|
|
|
| 1364 |
|
|
aux_symbols = (AUXU *) read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU),
|
| 1365 |
|
|
sym_hdr.cbAuxOffset, "Auxiliary symbols");
|
| 1366 |
|
|
|
| 1367 |
|
|
if (sym_hdr.iauxMax > 0)
|
| 1368 |
|
|
aux_used = (char *) xcalloc (sym_hdr.iauxMax, 1);
|
| 1369 |
|
|
|
| 1370 |
|
|
l_strings = (char *) read_seek (NULL, sym_hdr.issMax,
|
| 1371 |
|
|
sym_hdr.cbSsOffset, "Local string table");
|
| 1372 |
|
|
|
| 1373 |
|
|
e_strings = (char *) read_seek (NULL, sym_hdr.issExtMax,
|
| 1374 |
|
|
sym_hdr.cbSsExtOffset,
|
| 1375 |
|
|
"External string table");
|
| 1376 |
|
|
|
| 1377 |
|
|
file_desc = (FDR *) read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR),
|
| 1378 |
|
|
sym_hdr.cbFdOffset, "File tables");
|
| 1379 |
|
|
|
| 1380 |
|
|
rfile_desc = (ulong *) read_seek (NULL, sym_hdr.crfd * sizeof (ulong),
|
| 1381 |
|
|
sym_hdr.cbRfdOffset,
|
| 1382 |
|
|
"Relative file tables");
|
| 1383 |
|
|
|
| 1384 |
|
|
e_symbols = (EXTR *) read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR),
|
| 1385 |
|
|
sym_hdr.cbExtOffset, "External symbols");
|
| 1386 |
|
|
}
|
| 1387 |
|
|
|
| 1388 |
|
|
|
| 1389 |
|
|
|
| 1390 |
|
|
extern int main (int, char **);
|
| 1391 |
|
|
|
| 1392 |
|
|
int
|
| 1393 |
|
|
main (int argc, char **argv)
|
| 1394 |
|
|
{
|
| 1395 |
|
|
int i, opt;
|
| 1396 |
|
|
|
| 1397 |
|
|
/*
|
| 1398 |
|
|
* Process arguments
|
| 1399 |
|
|
*/
|
| 1400 |
|
|
while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1)
|
| 1401 |
|
|
switch (opt)
|
| 1402 |
|
|
{
|
| 1403 |
|
|
default: errors++; break;
|
| 1404 |
|
|
case 'a': want_aux++; break; /* print aux table */
|
| 1405 |
|
|
case 'l': want_line++; break; /* print line numbers */
|
| 1406 |
|
|
case 'r': want_rfd++; break; /* print relative fd's */
|
| 1407 |
|
|
case 's': want_scope++; break; /* print scope info */
|
| 1408 |
|
|
case 'v': verbose++; break; /* print version # */
|
| 1409 |
|
|
case 'V': version++; break; /* print version # */
|
| 1410 |
|
|
case 't': tfile++; break; /* this is a tfile (without header),
|
| 1411 |
|
|
and not a .o */
|
| 1412 |
|
|
}
|
| 1413 |
|
|
|
| 1414 |
|
|
if (version)
|
| 1415 |
|
|
{
|
| 1416 |
|
|
printf ("mips-tdump %s%s\n", pkgversion_string, version_string);
|
| 1417 |
|
|
fputs ("Copyright (C) 2010 Free Software Foundation, Inc.\n", stdout);
|
| 1418 |
|
|
fputs ("This is free software; see the source for copying conditions. There is NO\n\
|
| 1419 |
|
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n",
|
| 1420 |
|
|
stdout);
|
| 1421 |
|
|
exit (0);
|
| 1422 |
|
|
}
|
| 1423 |
|
|
|
| 1424 |
|
|
if (optind != argc - 1)
|
| 1425 |
|
|
errors++;
|
| 1426 |
|
|
|
| 1427 |
|
|
if (verbose || errors)
|
| 1428 |
|
|
{
|
| 1429 |
|
|
fprintf (stderr, "mips-tdump (GCC) %s", version_string);
|
| 1430 |
|
|
#ifdef TARGET_VERSION
|
| 1431 |
|
|
TARGET_VERSION;
|
| 1432 |
|
|
#endif
|
| 1433 |
|
|
fputc ('\n', stderr);
|
| 1434 |
|
|
}
|
| 1435 |
|
|
|
| 1436 |
|
|
if (errors)
|
| 1437 |
|
|
{
|
| 1438 |
|
|
fprintf (stderr, "Calling Sequence:\n");
|
| 1439 |
|
|
fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]);
|
| 1440 |
|
|
fprintf (stderr, "\n");
|
| 1441 |
|
|
fprintf (stderr, "switches:\n");
|
| 1442 |
|
|
fprintf (stderr, "\t-a Print out auxiliary table.\n");
|
| 1443 |
|
|
fprintf (stderr, "\t-l Print out line numbers.\n");
|
| 1444 |
|
|
fprintf (stderr, "\t-r Print out relative file descriptors.\n");
|
| 1445 |
|
|
fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
|
| 1446 |
|
|
fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
|
| 1447 |
|
|
fprintf (stderr, "\t-v Print program version.\n");
|
| 1448 |
|
|
return 1;
|
| 1449 |
|
|
}
|
| 1450 |
|
|
|
| 1451 |
|
|
/*
|
| 1452 |
|
|
* Open and process the input file.
|
| 1453 |
|
|
*/
|
| 1454 |
|
|
tfile_fd = open (argv[optind], O_RDONLY);
|
| 1455 |
|
|
if (tfile_fd < 0)
|
| 1456 |
|
|
{
|
| 1457 |
|
|
perror (argv[optind]);
|
| 1458 |
|
|
return 1;
|
| 1459 |
|
|
}
|
| 1460 |
|
|
|
| 1461 |
|
|
read_tfile ();
|
| 1462 |
|
|
|
| 1463 |
|
|
/*
|
| 1464 |
|
|
* Print any global aux words if any.
|
| 1465 |
|
|
*/
|
| 1466 |
|
|
if (want_aux)
|
| 1467 |
|
|
{
|
| 1468 |
|
|
long last_aux_in_use;
|
| 1469 |
|
|
|
| 1470 |
|
|
if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
|
| 1471 |
|
|
{
|
| 1472 |
|
|
printf ("\nGlobal auxiliary entries before first file:\n");
|
| 1473 |
|
|
for (i = 0; i < file_desc[0].iauxBase; i++)
|
| 1474 |
|
|
print_aux (aux_symbols[i], 0, aux_used[i]);
|
| 1475 |
|
|
}
|
| 1476 |
|
|
|
| 1477 |
|
|
if (sym_hdr.ifdMax == 0)
|
| 1478 |
|
|
last_aux_in_use = 0;
|
| 1479 |
|
|
else
|
| 1480 |
|
|
last_aux_in_use
|
| 1481 |
|
|
= (file_desc[sym_hdr.ifdMax-1].iauxBase
|
| 1482 |
|
|
+ file_desc[sym_hdr.ifdMax-1].caux - 1);
|
| 1483 |
|
|
|
| 1484 |
|
|
if (last_aux_in_use < sym_hdr.iauxMax-1)
|
| 1485 |
|
|
{
|
| 1486 |
|
|
printf ("\nGlobal auxiliary entries after last file:\n");
|
| 1487 |
|
|
for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
|
| 1488 |
|
|
print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
|
| 1489 |
|
|
}
|
| 1490 |
|
|
}
|
| 1491 |
|
|
|
| 1492 |
|
|
/*
|
| 1493 |
|
|
* Print the information for each file.
|
| 1494 |
|
|
*/
|
| 1495 |
|
|
for (i = 0; i < sym_hdr.ifdMax; i++)
|
| 1496 |
|
|
print_file_desc (&file_desc[i], i);
|
| 1497 |
|
|
|
| 1498 |
|
|
/*
|
| 1499 |
|
|
* Print the external symbols.
|
| 1500 |
|
|
*/
|
| 1501 |
|
|
want_scope = 0; /* scope info is meaning for extern symbols */
|
| 1502 |
|
|
printf ("\nThere are %lu external symbols, starting at %lu\n",
|
| 1503 |
|
|
(ulong) sym_hdr.iextMax,
|
| 1504 |
|
|
(ulong) sym_hdr.cbExtOffset);
|
| 1505 |
|
|
|
| 1506 |
|
|
for(i = 0; i < sym_hdr.iextMax; i++)
|
| 1507 |
|
|
print_symbol (&e_symbols[i].asym, i, e_strings,
|
| 1508 |
|
|
aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
|
| 1509 |
|
|
e_symbols[i].ifd,
|
| 1510 |
|
|
&file_desc[e_symbols[i].ifd]);
|
| 1511 |
|
|
|
| 1512 |
|
|
/*
|
| 1513 |
|
|
* Print unused aux symbols now.
|
| 1514 |
|
|
*/
|
| 1515 |
|
|
|
| 1516 |
|
|
if (want_aux)
|
| 1517 |
|
|
{
|
| 1518 |
|
|
int first_time = 1;
|
| 1519 |
|
|
|
| 1520 |
|
|
for (i = 0; i < sym_hdr.iauxMax; i++)
|
| 1521 |
|
|
{
|
| 1522 |
|
|
if (! aux_used[i])
|
| 1523 |
|
|
{
|
| 1524 |
|
|
if (first_time)
|
| 1525 |
|
|
{
|
| 1526 |
|
|
printf ("\nThe following auxiliary table entries were unused:\n\n");
|
| 1527 |
|
|
first_time = 0;
|
| 1528 |
|
|
}
|
| 1529 |
|
|
|
| 1530 |
|
|
printf (" #%-5d %11ld 0x%08lx %s\n",
|
| 1531 |
|
|
i,
|
| 1532 |
|
|
(long) aux_symbols[i].isym,
|
| 1533 |
|
|
(long) aux_symbols[i].isym,
|
| 1534 |
|
|
type_to_string (aux_symbols, i, (FDR *) 0));
|
| 1535 |
|
|
}
|
| 1536 |
|
|
}
|
| 1537 |
|
|
}
|
| 1538 |
|
|
|
| 1539 |
|
|
return 0;
|
| 1540 |
|
|
}
|