mips-tdump.c revision 169689
1294838Szbb/* Read and manage MIPS symbol tables from object modules. 2294838Szbb Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 3294838Szbb 2006 Free Software Foundation, Inc. 4294838Szbb Contributed by hartzell@boulder.colorado.edu, 5294838Szbb Rewritten by meissner@osf.org. 6294838Szbb 7294838SzbbThis file is part of GCC. 8294838Szbb 9294838SzbbGCC is free software; you can redistribute it and/or modify it under 10294838Szbbthe terms of the GNU General Public License as published by the Free 11294838SzbbSoftware Foundation; either version 2, or (at your option) any later 12294838Szbbversion. 13294838Szbb 14294838SzbbGCC is distributed in the hope that it will be useful, but WITHOUT ANY 15294838SzbbWARRANTY; without even the implied warranty of MERCHANTABILITY or 16294838SzbbFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17294838Szbbfor more details. 18294838Szbb 19294838SzbbYou should have received a copy of the GNU General Public License 20294838Szbbalong with GCC; see the file COPYING. If not, write to the Free 21294838SzbbSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 22294838Szbb02110-1301, USA. */ 23294838Szbb 24294838Szbb#include "config.h" 25294838Szbb#include "system.h" 26294838Szbb#include "coretypes.h" 27294838Szbb#include "tm.h" 28294838Szbb#include "version.h" 29294838Szbb#ifdef index 30294838Szbb#undef index 31294838Szbb#endif 32294838Szbb#ifndef CROSS_COMPILE 33294838Szbb#include <a.out.h> 34294838Szbb#else 35294838Szbb#include "mips/a.out.h" 36294838Szbb#endif /* CROSS_COMPILE */ 37294838Szbb 38294838Szbb/* Include getopt.h for the sake of getopt_long. */ 39294838Szbb#include "getopt.h" 40294838Szbb 41294838Szbb#ifndef MIPS_IS_STAB 42294838Szbb/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for 43294838Szbb and mips-tdump.c to print them out. This is used on the Alpha, 44294838Szbb which does not include mips.h. 45294838Szbb 46294838Szbb These must match the corresponding definitions in gdb/mipsread.c. 47294838Szbb Unfortunately, gcc and gdb do not currently share any directories. */ 48294838Szbb 49294838Szbb#define CODE_MASK 0x8F300 50294838Szbb#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK) 51294838Szbb#define MIPS_MARK_STAB(code) ((code)+CODE_MASK) 52294838Szbb#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK) 53294838Szbb#endif 54294838Szbb 55294838Szbb#define uchar unsigned char 56294838Szbb#define ushort unsigned short 57294838Szbb#define uint unsigned int 58294838Szbb#define ulong unsigned long 59294838Szbb 60294838Szbb 61294838Szbb/* Redefinition of storage classes as an enumeration for better 62294838Szbb debugging. */ 63294838Szbb 64294838Szbb#ifndef stStaParam 65294838Szbb#define stStaParam 16 /* Fortran static parameters */ 66294838Szbb#endif 67294838Szbb 68294838Szbb#ifndef btVoid 69294838Szbb#define btVoid 26 /* void basic type */ 70294838Szbb#endif 71294838Szbb 72294838Szbbtypedef enum sc { 73294838Szbb sc_Nil = scNil, /* no storage class */ 74294838Szbb sc_Text = scText, /* text symbol */ 75294838Szbb sc_Data = scData, /* initialized data symbol */ 76294838Szbb sc_Bss = scBss, /* un-initialized data symbol */ 77294838Szbb sc_Register = scRegister, /* value of symbol is register number */ 78294838Szbb sc_Abs = scAbs, /* value of symbol is absolute */ 79294838Szbb sc_Undefined = scUndefined, /* who knows? */ 80294838Szbb sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */ 81294838Szbb sc_Bits = scBits, /* this is a bit field */ 82294838Szbb sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */ 83294838Szbb sc_RegImage = scRegImage, /* register value saved on stack */ 84294838Szbb sc_Info = scInfo, /* symbol contains debugger information */ 85294838Szbb sc_UserStruct = scUserStruct, /* addr in struct user for current process */ 86294838Szbb sc_SData = scSData, /* load time only small data */ 87294838Szbb sc_SBss = scSBss, /* load time only small common */ 88294838Szbb sc_RData = scRData, /* load time only read only data */ 89294838Szbb sc_Var = scVar, /* Var parameter (fortran,pascal) */ 90294838Szbb sc_Common = scCommon, /* common variable */ 91294838Szbb sc_SCommon = scSCommon, /* small common */ 92294838Szbb sc_VarRegister = scVarRegister, /* Var parameter in a register */ 93294838Szbb sc_Variant = scVariant, /* Variant record */ 94294838Szbb sc_SUndefined = scSUndefined, /* small undefined(external) data */ 95294838Szbb sc_Init = scInit, /* .init section symbol */ 96294838Szbb sc_Max = scMax /* Max storage class+1 */ 97294838Szbb} sc_t; 98294838Szbb 99294838Szbb/* Redefinition of symbol type. */ 100294838Szbb 101294838Szbbtypedef enum st { 102294838Szbb st_Nil = stNil, /* Nuthin' special */ 103294838Szbb st_Global = stGlobal, /* external symbol */ 104294838Szbb st_Static = stStatic, /* static */ 105294838Szbb st_Param = stParam, /* procedure argument */ 106294838Szbb st_Local = stLocal, /* local variable */ 107294838Szbb st_Label = stLabel, /* label */ 108294838Szbb st_Proc = stProc, /* " " Procedure */ 109294838Szbb st_Block = stBlock, /* beginning of block */ 110294838Szbb st_End = stEnd, /* end (of anything) */ 111294838Szbb st_Member = stMember, /* member (of anything - struct/union/enum */ 112294838Szbb st_Typedef = stTypedef, /* type definition */ 113294838Szbb st_File = stFile, /* file name */ 114294838Szbb st_RegReloc = stRegReloc, /* register relocation */ 115294838Szbb st_Forward = stForward, /* forwarding address */ 116294838Szbb st_StaticProc = stStaticProc, /* load time only static procs */ 117294838Szbb st_StaParam = stStaParam, /* Fortran static parameters */ 118294838Szbb st_Constant = stConstant, /* const */ 119294838Szbb#ifdef stStruct 120294838Szbb st_Struct = stStruct, /* struct */ 121294838Szbb st_Union = stUnion, /* union */ 122294838Szbb st_Enum = stEnum, /* enum */ 123294838Szbb#endif 124294838Szbb st_Str = stStr, /* string */ 125294838Szbb st_Number = stNumber, /* pure number (i.e. 4 NOR 2+2) */ 126294838Szbb st_Expr = stExpr, /* 2+2 vs. 4 */ 127294838Szbb st_Type = stType, /* post-coercion SER */ 128294838Szbb st_Max = stMax /* max type+1 */ 129294838Szbb} st_t; 130294838Szbb 131294838Szbb/* Redefinition of type qualifiers. */ 132294838Szbb 133294838Szbbtypedef enum tq { 134294838Szbb tq_Nil = tqNil, /* bt is what you see */ 135294838Szbb tq_Ptr = tqPtr, /* pointer */ 136294838Szbb tq_Proc = tqProc, /* procedure */ 137294838Szbb tq_Array = tqArray, /* duh */ 138294838Szbb tq_Far = tqFar, /* longer addressing - 8086/8 land */ 139294838Szbb tq_Vol = tqVol, /* volatile */ 140294838Szbb tq_Max = tqMax /* Max type qualifier+1 */ 141294838Szbb} tq_t; 142294838Szbb 143294838Szbb/* Redefinition of basic types. */ 144294838Szbb 145294838Szbbtypedef enum bt { 146294838Szbb bt_Nil = btNil, /* undefined */ 147294838Szbb bt_Adr = btAdr, /* address - integer same size as pointer */ 148294838Szbb bt_Char = btChar, /* character */ 149294838Szbb bt_UChar = btUChar, /* unsigned character */ 150294838Szbb bt_Short = btShort, /* short */ 151294838Szbb bt_UShort = btUShort, /* unsigned short */ 152294838Szbb bt_Int = btInt, /* int */ 153294838Szbb bt_UInt = btUInt, /* unsigned int */ 154294838Szbb bt_Long = btLong, /* long */ 155294838Szbb bt_ULong = btULong, /* unsigned long */ 156294838Szbb bt_Float = btFloat, /* float (real) */ 157294838Szbb bt_Double = btDouble, /* Double (real) */ 158294838Szbb bt_Struct = btStruct, /* Structure (Record) */ 159294838Szbb bt_Union = btUnion, /* Union (variant) */ 160294838Szbb bt_Enum = btEnum, /* Enumerated */ 161294838Szbb bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */ 162294838Szbb bt_Range = btRange, /* subrange of int */ 163294838Szbb bt_Set = btSet, /* pascal sets */ 164294838Szbb bt_Complex = btComplex, /* fortran complex */ 165294838Szbb bt_DComplex = btDComplex, /* fortran double complex */ 166294838Szbb bt_Indirect = btIndirect, /* forward or unnamed typedef */ 167294838Szbb bt_FixedDec = btFixedDec, /* Fixed Decimal */ 168294838Szbb bt_FloatDec = btFloatDec, /* Float Decimal */ 169294838Szbb bt_String = btString, /* Varying Length Character String */ 170294838Szbb bt_Bit = btBit, /* Aligned Bit String */ 171294838Szbb bt_Picture = btPicture, /* Picture */ 172294838Szbb bt_Void = btVoid, /* void */ 173294838Szbb bt_Max = btMax /* Max basic type+1 */ 174294838Szbb} bt_t; 175294838Szbb 176294838Szbb/* Redefinition of the language codes. */ 177294838Szbb 178294838Szbbtypedef enum lang { 179294838Szbb lang_C = langC, 180294838Szbb lang_Pascal = langPascal, 181294838Szbb lang_Fortran = langFortran, 182294838Szbb lang_Assembler = langAssembler, 183294838Szbb lang_Machine = langMachine, 184294838Szbb lang_Nil = langNil, 185294838Szbb lang_Ada = langAda, 186294838Szbb lang_Pl1 = langPl1, 187294838Szbb lang_Cobol = langCobol 188294838Szbb} lang_t; 189294838Szbb 190294838Szbb/* Redefinition of the debug level codes. */ 191294838Szbb 192294838Szbbtypedef enum glevel { 193294838Szbb glevel_0 = GLEVEL_0, 194294838Szbb glevel_1 = GLEVEL_1, 195294838Szbb glevel_2 = GLEVEL_2, 196294838Szbb glevel_3 = GLEVEL_3 197294838Szbb} glevel_t; 198294838Szbb 199294838Szbb 200294838Szbb/* Keep track of the active scopes. */ 201294838Szbbtypedef struct scope { 202294838Szbb struct scope *prev; /* previous scope */ 203294838Szbb ulong open_sym; /* symbol opening scope */ 204294838Szbb sc_t sc; /* storage class */ 205294838Szbb st_t st; /* symbol type */ 206294838Szbb} scope_t; 207294838Szbb 208294838Szbbstruct filehdr global_hdr; /* a.out header */ 209294838Szbb 210294838Szbbint errors = 0; /* # of errors */ 211294838Szbbint want_aux = 0; /* print aux table */ 212294838Szbbint want_line = 0; /* print line numbers */ 213294838Szbbint want_rfd = 0; /* print relative file desc's */ 214294838Szbbint want_scope = 0; /* print scopes for every symbol */ 215294838Szbbint tfile = 0; /* no global header file */ 216294838Szbbint version = 0; /* print version # */ 217294838Szbbint verbose = 0; 218294838Szbbint tfile_fd; /* file descriptor of .T file */ 219294838Szbboff_t tfile_offset; /* current offset in .T file */ 220294838Szbbscope_t *cur_scope = 0; /* list of active scopes */ 221294838Szbbscope_t *free_scope = 0; /* list of freed scopes */ 222294838SzbbHDRR sym_hdr; /* symbolic header */ 223294838Szbbchar *l_strings; /* local strings */ 224294838Szbbchar *e_strings; /* external strings */ 225294838SzbbSYMR *l_symbols; /* local symbols */ 226294838SzbbEXTR *e_symbols; /* external symbols */ 227294838SzbbLINER *lines; /* line numbers */ 228294838SzbbDNR *dense_nums; /* dense numbers */ 229294838SzbbOPTR *opt_symbols; /* optimization symbols */ 230294838SzbbAUXU *aux_symbols; /* Auxiliary symbols */ 231294838Szbbchar *aux_used; /* map of which aux syms are used */ 232294838SzbbFDR *file_desc; /* file tables */ 233294838Szbbulong *rfile_desc; /* relative file tables */ 234294838SzbbPDR *proc_desc; /* procedure tables */ 235294838Szbb 236294838Szbb/* Forward reference for functions. */ 237294838Szbbstatic void *read_seek (void *, size_t, off_t, const char *); 238294838Szbbstatic void read_tfile (void); 239294838Szbbstatic void print_global_hdr (struct filehdr *); 240294838Szbbstatic void print_sym_hdr (HDRR *); 241294838Szbbstatic void print_file_desc (FDR *, int); 242294838Szbbstatic void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *); 243294838Szbbstatic void print_aux (AUXU, int, int); 244294838Szbbstatic void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *); 245294838Szbbstatic const char *st_to_string (st_t); 246294838Szbbstatic const char *sc_to_string (sc_t); 247294838Szbbstatic const char *glevel_to_string (glevel_t); 248294838Szbbstatic const char *lang_to_string (lang_t); 249294838Szbbstatic const char *type_to_string (AUXU *, int, FDR *); 250294838Szbb 251294838Szbbextern char *optarg; 252294838Szbbextern int optind; 253294838Szbbextern int opterr; 254294838Szbb 255294838Szbb/* Create a table of debugging stab-codes and corresponding names. */ 256294838Szbb 257294838Szbb#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING}, 258294838Szbbconst struct {const short code; const char string[10];} stab_names[] = { 259294838Szbb#include "stab.def" 260294838Szbb#undef __define_stab 261294838Szbb}; 262294838Szbb 263294838Szbb/* Command line options for getopt_long. */ 264294838Szbb 265294838Szbbstatic const struct option options[] = 266294838Szbb{ 267294838Szbb { "version", 0, 0, 'V' }, 268294838Szbb { "verbose", 0, 0, 'v' }, 269294838Szbb { 0, 0, 0, 0 } 270294838Szbb}; 271294838Szbb 272294838Szbb/* Read some bytes at a specified location, and return a pointer. 273294838Szbb Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE 274294838Szbb bytes from offset OFFSET. In case of errors CONTEXT is used as 275294838Szbb error message. */ 276294838Szbb 277294838Szbbstatic void * 278294838Szbbread_seek (void *ptr, size_t size, off_t offset, const char *context) 279294838Szbb{ 280294838Szbb long read_size = 0; 281294838Szbb 282294838Szbb if (size == 0) /* nothing to read */ 283294838Szbb return ptr; 284294838Szbb 285294838Szbb if (!ptr) 286294838Szbb ptr = xmalloc (size); 287294838Szbb 288294838Szbb if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1) 289294838Szbb || (read_size = read (tfile_fd, ptr, size)) < 0) 290294838Szbb { 291294838Szbb perror (context); 292294838Szbb exit (1); 293294838Szbb } 294294838Szbb 295294838Szbb if (read_size != (long) size) 296294838Szbb { 297294838Szbb fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n", 298294838Szbb context, read_size, (long) size); 299294838Szbb exit (1); 300294838Szbb } 301294838Szbb 302294838Szbb tfile_offset = offset + size; 303294838Szbb return ptr; 304294838Szbb} 305294838Szbb 306294838Szbb 307294838Szbb/* Convert language code to string format. */ 308294838Szbb 309294838Szbbstatic const char * 310294838Szbblang_to_string (lang_t lang) 311294838Szbb{ 312294838Szbb switch (lang) 313294838Szbb { 314294838Szbb case langC: return "C"; 315294838Szbb case langPascal: return "Pascal"; 316294838Szbb case langFortran: return "Fortran"; 317294838Szbb case langAssembler: return "Assembler"; 318294838Szbb case langMachine: return "Machine"; 319294838Szbb case langNil: return "Nil"; 320294838Szbb case langAda: return "Ada"; 321294838Szbb case langPl1: return "Pl1"; 322294838Szbb case langCobol: return "Cobol"; 323294838Szbb } 324294838Szbb 325294838Szbb return "Unknown language"; 326294838Szbb} 327294838Szbb 328294838Szbb 329294838Szbb/* Convert storage class to string. */ 330294838Szbb 331294838Szbbstatic const char * 332294838Szbbsc_to_string (sc_t storage_class) 333294838Szbb{ 334294838Szbb switch(storage_class) 335294838Szbb { 336294838Szbb case sc_Nil: return "Nil"; 337294838Szbb case sc_Text: return "Text"; 338294838Szbb case sc_Data: return "Data"; 339294838Szbb case sc_Bss: return "Bss"; 340294838Szbb case sc_Register: return "Register"; 341294838Szbb case sc_Abs: return "Abs"; 342294838Szbb case sc_Undefined: return "Undefined"; 343294838Szbb case sc_CdbLocal: return "CdbLocal"; 344294838Szbb case sc_Bits: return "Bits"; 345294838Szbb case sc_CdbSystem: return "CdbSystem"; 346294838Szbb case sc_RegImage: return "RegImage"; 347294838Szbb case sc_Info: return "Info"; 348294838Szbb case sc_UserStruct: return "UserStruct"; 349294838Szbb case sc_SData: return "SData"; 350294838Szbb case sc_SBss: return "SBss"; 351294838Szbb case sc_RData: return "RData"; 352294838Szbb case sc_Var: return "Var"; 353294838Szbb case sc_Common: return "Common"; 354294838Szbb case sc_SCommon: return "SCommon"; 355294838Szbb case sc_VarRegister: return "VarRegister"; 356294838Szbb case sc_Variant: return "Variant"; 357294838Szbb case sc_SUndefined: return "SUndefined"; 358294838Szbb case sc_Init: return "Init"; 359294838Szbb case sc_Max: return "Max"; 360294838Szbb } 361294838Szbb 362294838Szbb return "???"; 363294838Szbb} 364294838Szbb 365294838Szbb 366294838Szbb/* Convert symbol type to string. */ 367294838Szbb 368294838Szbbstatic const char * 369294838Szbbst_to_string (st_t symbol_type) 370294838Szbb{ 371294838Szbb switch(symbol_type) 372294838Szbb { 373294838Szbb case st_Nil: return "Nil"; 374294838Szbb case st_Global: return "Global"; 375294838Szbb case st_Static: return "Static"; 376294838Szbb case st_Param: return "Param"; 377294838Szbb case st_Local: return "Local"; 378294838Szbb case st_Label: return "Label"; 379294838Szbb case st_Proc: return "Proc"; 380294838Szbb case st_Block: return "Block"; 381294838Szbb case st_End: return "End"; 382294838Szbb case st_Member: return "Member"; 383294838Szbb case st_Typedef: return "Typedef"; 384294838Szbb case st_File: return "File"; 385294838Szbb case st_RegReloc: return "RegReloc"; 386294838Szbb case st_Forward: return "Forward"; 387294838Szbb case st_StaticProc: return "StaticProc"; 388294838Szbb case st_Constant: return "Constant"; 389294838Szbb case st_StaParam: return "StaticParam"; 390294838Szbb#ifdef stStruct 391294838Szbb case st_Struct: return "Struct"; 392294838Szbb case st_Union: return "Union"; 393294838Szbb case st_Enum: return "Enum"; 394294838Szbb#endif 395294838Szbb case st_Str: return "String"; 396294838Szbb case st_Number: return "Number"; 397294838Szbb case st_Expr: return "Expr"; 398294838Szbb case st_Type: return "Type"; 399294838Szbb case st_Max: return "Max"; 400294838Szbb } 401294838Szbb 402294838Szbb return "???"; 403294838Szbb} 404294838Szbb 405294838Szbb 406294838Szbb/* Convert debug level to string. */ 407294838Szbb 408294838Szbbstatic const char * 409294838Szbbglevel_to_string (glevel_t g_level) 410294838Szbb{ 411294838Szbb switch(g_level) 412294838Szbb { 413294838Szbb case GLEVEL_0: return "G0"; 414294838Szbb case GLEVEL_1: return "G1"; 415 case GLEVEL_2: return "G2"; 416 case GLEVEL_3: return "G3"; 417 } 418 419 return "??"; 420} 421 422 423/* Convert the type information to string format. */ 424 425static const char * 426type_to_string (AUXU *aux_ptr, int index, FDR *fdp) 427{ 428 AUXU u; 429 struct qual { 430 tq_t type; 431 int low_bound; 432 int high_bound; 433 int stride; 434 } qualifiers[7]; 435 436 bt_t basic_type; 437 int i; 438 static char buffer1[1024]; 439 static char buffer2[1024]; 440 char *p1 = buffer1; 441 char *p2 = buffer2; 442 char *used_ptr = aux_used + (aux_ptr - aux_symbols); 443 444 for (i = 0; i < 7; i++) 445 { 446 qualifiers[i].low_bound = 0; 447 qualifiers[i].high_bound = 0; 448 qualifiers[i].stride = 0; 449 } 450 451 used_ptr[index] = 1; 452 u = aux_ptr[index++]; 453 if (u.isym == -1) 454 return "-1 (no type)"; 455 456 basic_type = (bt_t) u.ti.bt; 457 qualifiers[0].type = (tq_t) u.ti.tq0; 458 qualifiers[1].type = (tq_t) u.ti.tq1; 459 qualifiers[2].type = (tq_t) u.ti.tq2; 460 qualifiers[3].type = (tq_t) u.ti.tq3; 461 qualifiers[4].type = (tq_t) u.ti.tq4; 462 qualifiers[5].type = (tq_t) u.ti.tq5; 463 qualifiers[6].type = tq_Nil; 464 465 /* 466 * Go get the basic type. 467 */ 468 switch (basic_type) 469 { 470 case bt_Nil: /* undefined */ 471 strcpy (p1, "nil"); 472 break; 473 474 case bt_Adr: /* address - integer same size as pointer */ 475 strcpy (p1, "address"); 476 break; 477 478 case bt_Char: /* character */ 479 strcpy (p1, "char"); 480 break; 481 482 case bt_UChar: /* unsigned character */ 483 strcpy (p1, "unsigned char"); 484 break; 485 486 case bt_Short: /* short */ 487 strcpy (p1, "short"); 488 break; 489 490 case bt_UShort: /* unsigned short */ 491 strcpy (p1, "unsigned short"); 492 break; 493 494 case bt_Int: /* int */ 495 strcpy (p1, "int"); 496 break; 497 498 case bt_UInt: /* unsigned int */ 499 strcpy (p1, "unsigned int"); 500 break; 501 502 case bt_Long: /* long */ 503 strcpy (p1, "long"); 504 break; 505 506 case bt_ULong: /* unsigned long */ 507 strcpy (p1, "unsigned long"); 508 break; 509 510 case bt_Float: /* float (real) */ 511 strcpy (p1, "float"); 512 break; 513 514 case bt_Double: /* Double (real) */ 515 strcpy (p1, "double"); 516 break; 517 518 /* Structures add 1-2 aux words: 519 1st word is [ST_RFDESCAPE, offset] pointer to struct def; 520 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 521 522 case bt_Struct: /* Structure (Record) */ 523 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp); 524 used_ptr[index] = 1; 525 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 526 used_ptr[++index] = 1; 527 528 index++; /* skip aux words */ 529 break; 530 531 /* Unions add 1-2 aux words: 532 1st word is [ST_RFDESCAPE, offset] pointer to union def; 533 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 534 535 case bt_Union: /* Union */ 536 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp); 537 used_ptr[index] = 1; 538 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 539 used_ptr[++index] = 1; 540 541 index++; /* skip aux words */ 542 break; 543 544 /* Enumerations add 1-2 aux words: 545 1st word is [ST_RFDESCAPE, offset] pointer to enum def; 546 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 547 548 case bt_Enum: /* Enumeration */ 549 emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp); 550 used_ptr[index] = 1; 551 if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 552 used_ptr[++index] = 1; 553 554 index++; /* skip aux words */ 555 break; 556 557 case bt_Typedef: /* defined via a typedef, isymRef points */ 558 strcpy (p1, "typedef"); 559 break; 560 561 case bt_Range: /* subrange of int */ 562 strcpy (p1, "subrange"); 563 break; 564 565 case bt_Set: /* pascal sets */ 566 strcpy (p1, "set"); 567 break; 568 569 case bt_Complex: /* fortran complex */ 570 strcpy (p1, "complex"); 571 break; 572 573 case bt_DComplex: /* fortran double complex */ 574 strcpy (p1, "double complex"); 575 break; 576 577 case bt_Indirect: /* forward or unnamed typedef */ 578 strcpy (p1, "forward/unnamed typedef"); 579 break; 580 581 case bt_FixedDec: /* Fixed Decimal */ 582 strcpy (p1, "fixed decimal"); 583 break; 584 585 case bt_FloatDec: /* Float Decimal */ 586 strcpy (p1, "float decimal"); 587 break; 588 589 case bt_String: /* Varying Length Character String */ 590 strcpy (p1, "string"); 591 break; 592 593 case bt_Bit: /* Aligned Bit String */ 594 strcpy (p1, "bit"); 595 break; 596 597 case bt_Picture: /* Picture */ 598 strcpy (p1, "picture"); 599 break; 600 601 case bt_Void: /* Void */ 602 strcpy (p1, "void"); 603 break; 604 605 default: 606 sprintf (p1, "Unknown basic type %d", (int) basic_type); 607 break; 608 } 609 610 p1 += strlen (buffer1); 611 612 /* 613 * If this is a bitfield, get the bitsize. 614 */ 615 if (u.ti.fBitfield) 616 { 617 int bitsize; 618 619 used_ptr[index] = 1; 620 bitsize = aux_ptr[index++].width; 621 sprintf (p1, " : %d", bitsize); 622 p1 += strlen (buffer1); 623 } 624 625 626 /* 627 * Deal with any qualifiers. 628 */ 629 if (qualifiers[0].type != tq_Nil) 630 { 631 /* 632 * Snarf up any array bounds in the correct order. Arrays 633 * store 5 successive words in the aux. table: 634 * word 0 RNDXR to type of the bounds (i.e., int) 635 * word 1 Current file descriptor index 636 * word 2 low bound 637 * word 3 high bound (or -1 if []) 638 * word 4 stride size in bits 639 */ 640 for (i = 0; i < 7; i++) 641 { 642 if (qualifiers[i].type == tq_Array) 643 { 644 qualifiers[i].low_bound = aux_ptr[index+2].dnLow; 645 qualifiers[i].high_bound = aux_ptr[index+3].dnHigh; 646 qualifiers[i].stride = aux_ptr[index+4].width; 647 used_ptr[index] = 1; 648 used_ptr[index+1] = 1; 649 used_ptr[index+2] = 1; 650 used_ptr[index+3] = 1; 651 used_ptr[index+4] = 1; 652 index += 5; 653 } 654 } 655 656 /* 657 * Now print out the qualifiers. 658 */ 659 for (i = 0; i < 6; i++) 660 { 661 switch (qualifiers[i].type) 662 { 663 case tq_Nil: 664 case tq_Max: 665 break; 666 667 case tq_Ptr: 668 strcpy (p2, "ptr to "); 669 p2 += sizeof ("ptr to ")-1; 670 break; 671 672 case tq_Vol: 673 strcpy (p2, "volatile "); 674 p2 += sizeof ("volatile ")-1; 675 break; 676 677 case tq_Far: 678 strcpy (p2, "far "); 679 p2 += sizeof ("far ")-1; 680 break; 681 682 case tq_Proc: 683 strcpy (p2, "func. ret. "); 684 p2 += sizeof ("func. ret. "); 685 break; 686 687 case tq_Array: 688 { 689 int first_array = i; 690 int j; 691 692 /* Print array bounds reversed (i.e., in the order the C 693 programmer writes them). C is such a fun language.... */ 694 695 while (i < 5 && qualifiers[i+1].type == tq_Array) 696 i++; 697 698 for (j = i; j >= first_array; j--) 699 { 700 strcpy (p2, "array ["); 701 p2 += sizeof ("array [")-1; 702 if (qualifiers[j].low_bound != 0) 703 sprintf (p2, 704 "%ld:%ld {%ld bits}", 705 (long) qualifiers[j].low_bound, 706 (long) qualifiers[j].high_bound, 707 (long) qualifiers[j].stride); 708 709 else if (qualifiers[j].high_bound != -1) 710 sprintf (p2, 711 "%ld {%ld bits}", 712 (long) (qualifiers[j].high_bound + 1), 713 (long) (qualifiers[j].stride)); 714 715 else 716 sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride)); 717 718 p2 += strlen (p2); 719 strcpy (p2, "] of "); 720 p2 += sizeof ("] of ")-1; 721 } 722 } 723 break; 724 } 725 } 726 } 727 728 strcpy (p2, buffer1); 729 return buffer2; 730} 731 732 733/* Print out the global file header for object files. */ 734 735static void 736print_global_hdr (struct filehdr *ptr) 737{ 738 char *time = ctime ((time_t *)&ptr->f_timdat); 739 ushort flags = ptr->f_flags; 740 741 printf("Global file header:\n"); 742 printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic); 743 printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns); 744 printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time); 745 printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr); 746 printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms); 747 printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr); 748 printf(" %-*s 0x%x", 24, "flags", (ushort) flags); 749 750 if ((flags & F_RELFLG) != 0) 751 printf (", F_RELFLG"); 752 753 if ((flags & F_EXEC) != 0) 754 printf (", F_EXEC"); 755 756 if ((flags & F_LNNO) != 0) 757 printf (", F_LNNO"); 758 759 if ((flags & F_LSYMS) != 0) 760 printf (", F_LSYMS"); 761 762 if ((flags & F_MINMAL) != 0) 763 printf (", F_MINMAL"); 764 765 if ((flags & F_UPDATE) != 0) 766 printf (", F_UPDATE"); 767 768 if ((flags & F_SWABD) != 0) 769 printf (", F_SWABD"); 770 771 if ((flags & F_AR16WR) != 0) 772 printf (", F_AR16WR"); 773 774 if ((flags & F_AR32WR) != 0) 775 printf (", F_AR32WR"); 776 777 if ((flags & F_AR32W) != 0) 778 printf (", F_AR32W"); 779 780 if ((flags & F_PATCH) != 0) 781 printf (", F_PATCH/F_NODF"); 782 783 printf ("\n\n"); 784} 785 786 787/* Print out the symbolic header. */ 788 789static void 790print_sym_hdr (HDRR *sym_ptr) 791{ 792 int width = 20; 793 794 printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n", 795 sym_ptr->magic & 0xffff, 796 (sym_ptr->vstamp & 0xffff) >> 8, 797 sym_ptr->vstamp & 0xff); 798 799 printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes"); 800 printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n"); 801 802 printf(" %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers", 803 (long) sym_ptr->cbLineOffset, 804 (long) sym_ptr->cbLine, 805 (long) sym_ptr->cbLine, 806 (int) sym_ptr->ilineMax); 807 808 printf(" %-*s %11ld %11ld %11ld\n", width, "Dense numbers", 809 (long) sym_ptr->cbDnOffset, 810 (long) sym_ptr->idnMax, 811 (long) (sym_ptr->idnMax * sizeof (DNR))); 812 813 printf(" %-*s %11ld %11ld %11ld\n", width, "Procedures Tables", 814 (long) sym_ptr->cbPdOffset, 815 (long) sym_ptr->ipdMax, 816 (long) (sym_ptr->ipdMax * sizeof (PDR))); 817 818 printf(" %-*s %11ld %11ld %11ld\n", width, "Local Symbols", 819 (long) sym_ptr->cbSymOffset, 820 (long) sym_ptr->isymMax, 821 (long) (sym_ptr->isymMax * sizeof (SYMR))); 822 823 printf(" %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols", 824 (long) sym_ptr->cbOptOffset, 825 (long) sym_ptr->ioptMax, 826 (long) (sym_ptr->ioptMax * sizeof (OPTR))); 827 828 printf(" %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols", 829 (long) sym_ptr->cbAuxOffset, 830 (long) sym_ptr->iauxMax, 831 (long) (sym_ptr->iauxMax * sizeof (AUXU))); 832 833 printf(" %-*s %11ld %11ld %11ld\n", width, "Local Strings", 834 (long) sym_ptr->cbSsOffset, 835 (long) sym_ptr->issMax, 836 (long) sym_ptr->issMax); 837 838 printf(" %-*s %11ld %11ld %11ld\n", width, "External Strings", 839 (long) sym_ptr->cbSsExtOffset, 840 (long) sym_ptr->issExtMax, 841 (long) sym_ptr->issExtMax); 842 843 printf(" %-*s %11ld %11ld %11ld\n", width, "File Tables", 844 (long) sym_ptr->cbFdOffset, 845 (long) sym_ptr->ifdMax, 846 (long) (sym_ptr->ifdMax * sizeof (FDR))); 847 848 printf(" %-*s %11ld %11ld %11ld\n", width, "Relative Files", 849 (long) sym_ptr->cbRfdOffset, 850 (long) sym_ptr->crfd, 851 (long) (sym_ptr->crfd * sizeof (ulong))); 852 853 printf(" %-*s %11ld %11ld %11ld\n", width, "External Symbols", 854 (long) sym_ptr->cbExtOffset, 855 (long) sym_ptr->iextMax, 856 (long) (sym_ptr->iextMax * sizeof (EXTR))); 857} 858 859 860/* Print out a symbol. */ 861 862static void 863print_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base, 864 int ifd, FDR *fdp) 865{ 866 sc_t storage_class = (sc_t) sym_ptr->sc; 867 st_t symbol_type = (st_t) sym_ptr->st; 868 ulong index = sym_ptr->index; 869 char *used_ptr = aux_used + (aux_base - aux_symbols); 870 scope_t *scope_ptr; 871 872 printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase); 873 874 if (aux_base != (AUXU *) 0 && index != indexNil) 875 switch (symbol_type) 876 { 877 case st_Nil: 878 case st_Label: 879 break; 880 881 case st_File: 882 case st_Block: 883 printf (" End+1 symbol: %ld\n", index); 884 if (want_scope) 885 { 886 if (free_scope == (scope_t *) 0) 887 scope_ptr = xmalloc (sizeof (scope_t)); 888 else 889 { 890 scope_ptr = free_scope; 891 free_scope = scope_ptr->prev; 892 } 893 scope_ptr->open_sym = number; 894 scope_ptr->st = symbol_type; 895 scope_ptr->sc = storage_class; 896 scope_ptr->prev = cur_scope; 897 cur_scope = scope_ptr; 898 } 899 break; 900 901 case st_End: 902 if (storage_class == sc_Text || storage_class == sc_Info) 903 printf (" First symbol: %ld\n", index); 904 else 905 { 906 used_ptr[index] = 1; 907 printf (" First symbol: %ld\n", (long) aux_base[index].isym); 908 } 909 910 if (want_scope) 911 { 912 if (cur_scope == (scope_t *) 0) 913 printf (" Can't pop end scope\n"); 914 else 915 { 916 scope_ptr = cur_scope; 917 cur_scope = scope_ptr->prev; 918 scope_ptr->prev = free_scope; 919 free_scope = scope_ptr; 920 } 921 } 922 break; 923 924 case st_Proc: 925 case st_StaticProc: 926 if (MIPS_IS_STAB(sym_ptr)) 927 ; 928 else if (ifd == -1) /* local symbol */ 929 { 930 used_ptr[index] = used_ptr[index+1] = 1; 931 printf (" End+1 symbol: %-7ld Type: %s\n", 932 (long) aux_base[index].isym, 933 type_to_string (aux_base, index+1, fdp)); 934 } 935 else /* global symbol */ 936 printf (" Local symbol: %ld\n", index); 937 938 if (want_scope) 939 { 940 if (free_scope == (scope_t *) 0) 941 scope_ptr = xmalloc (sizeof (scope_t)); 942 else 943 { 944 scope_ptr = free_scope; 945 free_scope = scope_ptr->prev; 946 } 947 scope_ptr->open_sym = number; 948 scope_ptr->st = symbol_type; 949 scope_ptr->sc = storage_class; 950 scope_ptr->prev = cur_scope; 951 cur_scope = scope_ptr; 952 } 953 break; 954 955#ifdef stStruct 956 case st_Struct: 957 case st_Union: 958 case st_Enum: 959 printf (" End+1 symbol: %lu\n", index); 960 break; 961#endif 962 963 default: 964 if (!MIPS_IS_STAB (sym_ptr)) 965 { 966 used_ptr[index] = 1; 967 printf (" Type: %s\n", 968 type_to_string (aux_base, index, fdp)); 969 } 970 break; 971 } 972 973 if (want_scope) 974 { 975 printf (" Scopes: "); 976 if (cur_scope == (scope_t *) 0) 977 printf (" none\n"); 978 else 979 { 980 for (scope_ptr = cur_scope; 981 scope_ptr != (scope_t *) 0; 982 scope_ptr = scope_ptr->prev) 983 { 984 const char *class; 985 if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc) 986 class = "func."; 987 else if (scope_ptr->st == st_File) 988 class = "file"; 989 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text) 990 class = "block"; 991 else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info) 992 class = "type"; 993 else 994 class = "???"; 995 996 printf (" %ld [%s]", scope_ptr->open_sym, class); 997 } 998 printf ("\n"); 999 } 1000 } 1001 1002 printf (" Value: %-13ld ", 1003 (long)sym_ptr->value); 1004 if (ifd == -1) 1005 printf ("String index: %ld\n", (long)sym_ptr->iss); 1006 else 1007 printf ("String index: %-11ld Ifd: %d\n", 1008 (long)sym_ptr->iss, ifd); 1009 1010 printf (" Symbol type: %-11sStorage class: %-11s", 1011 st_to_string (symbol_type), sc_to_string (storage_class)); 1012 1013 if (MIPS_IS_STAB(sym_ptr)) 1014 { 1015 int i = ARRAY_SIZE (stab_names); 1016 const char *stab_name = "stab"; 1017 short code = MIPS_UNMARK_STAB(sym_ptr->index); 1018 1019 while (--i >= 0) 1020 if (stab_names[i].code == code) 1021 { 1022 stab_name = stab_names[i].string; 1023 break; 1024 } 1025 printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name); 1026 } 1027 else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil) 1028 printf ("Index: %ld (line#)\n", (long)sym_ptr->index); 1029 else 1030 printf ("Index: %ld\n", (long)sym_ptr->index); 1031 1032} 1033 1034 1035/* Print out a word from the aux. table in various formats. */ 1036 1037static void 1038print_aux (AUXU u, int auxi, int used) 1039{ 1040 printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n", 1041 (used) ? " " : "* ", 1042 auxi, 1043 (long) u.isym, 1044 (long) u.rndx.rfd, 1045 (long) u.rndx.index, 1046 u.ti.bt, 1047 u.ti.fBitfield, 1048 u.ti.continued, 1049 u.ti.tq0, 1050 u.ti.tq1, 1051 u.ti.tq2, 1052 u.ti.tq3, 1053 u.ti.tq4, 1054 u.ti.tq5); 1055} 1056 1057 1058/* Write aggregate information to a string. */ 1059 1060static void 1061emit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp) 1062{ 1063 unsigned int ifd = u.rndx.rfd; 1064 unsigned int index = u.rndx.index; 1065 const char *name; 1066 1067 if (ifd == ST_RFDESCAPE) 1068 ifd = u2.isym; 1069 1070 /* An ifd of -1 is an opaque type. An escaped index of 0 is a 1071 struct return type of a procedure compiled without -g. */ 1072 if (ifd == 0xffffffff 1073 || (u.rndx.rfd == ST_RFDESCAPE && index == 0)) 1074 name = "<undefined>"; 1075 else if (index == indexNil) 1076 name = "<no name>"; 1077 else 1078 { 1079 if (fdp == 0 || sym_hdr.crfd == 0) 1080 fdp = &file_desc[ifd]; 1081 else 1082 fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]]; 1083 name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss]; 1084 } 1085 1086 sprintf (string, 1087 "%s %s { ifd = %u, index = %u }", 1088 which, name, ifd, index); 1089} 1090 1091 1092/* Print out information about a file descriptor, and the symbols, 1093 procedures, and line numbers within it. */ 1094 1095static void 1096print_file_desc (FDR *fdp, int number) 1097{ 1098 char *str_base; 1099 AUXU *aux_base; 1100 int symi, pdi; 1101 int width = 20; 1102 char *used_base; 1103 1104 str_base = l_strings + fdp->issBase; 1105 aux_base = aux_symbols + fdp->iauxBase; 1106 used_base = aux_used + (aux_base - aux_symbols); 1107 1108 printf ("\nFile #%d, \"%s\"\n\n", 1109 number, 1110 fdp->rss != issNil ? str_base + fdp->rss : "<unknown>"); 1111 1112 printf (" Name index = %-10ld Readin = %s\n", 1113 (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No"); 1114 1115 printf (" Merge = %-10s Endian = %s\n", 1116 (fdp->fMerge) ? "Yes" : "No", 1117 (fdp->fBigendian) ? "BIG" : "LITTLE"); 1118 1119 printf (" Debug level = %-10s Language = %s\n", 1120 glevel_to_string (fdp->glevel), 1121 lang_to_string((lang_t) fdp->lang)); 1122 1123 printf (" Adr = 0x%08lx\n\n", (long) fdp->adr); 1124 1125 printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset"); 1126 printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======"); 1127 1128 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1129 width, "Local strings", 1130 (ulong) fdp->issBase, 1131 (ulong) fdp->cbSs, 1132 (ulong) fdp->cbSs, 1133 (ulong) (fdp->issBase + sym_hdr.cbSsOffset)); 1134 1135 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1136 width, "Local symbols", 1137 (ulong) fdp->isymBase, 1138 (ulong) fdp->csym, 1139 (ulong) (fdp->csym * sizeof (SYMR)), 1140 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset)); 1141 1142 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1143 width, "Line numbers", 1144 (ulong) fdp->cbLineOffset, 1145 (ulong) fdp->cline, 1146 (ulong) fdp->cbLine, 1147 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset)); 1148 1149 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1150 width, "Optimization symbols", 1151 (ulong) fdp->ioptBase, 1152 (ulong) fdp->copt, 1153 (ulong) (fdp->copt * sizeof (OPTR)), 1154 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset)); 1155 1156 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1157 width, "Procedures", 1158 (ulong) fdp->ipdFirst, 1159 (ulong) fdp->cpd, 1160 (ulong) (fdp->cpd * sizeof (PDR)), 1161 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset)); 1162 1163 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1164 width, "Auxiliary symbols", 1165 (ulong) fdp->iauxBase, 1166 (ulong) fdp->caux, 1167 (ulong) (fdp->caux * sizeof (AUXU)), 1168 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset)); 1169 1170 printf(" %-*s %11lu %11lu %11lu %11lu\n", 1171 width, "Relative Files", 1172 (ulong) fdp->rfdBase, 1173 (ulong) fdp->crfd, 1174 (ulong) (fdp->crfd * sizeof (ulong)), 1175 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset)); 1176 1177 1178 if (want_scope && cur_scope != (scope_t *) 0) 1179 printf ("\n Warning scope does not start at 0!\n"); 1180 1181 /* 1182 * print the info about the symbol table. 1183 */ 1184 printf ("\n There are %lu local symbols, starting at %lu\n", 1185 (ulong) fdp->csym, 1186 (ulong) (fdp->isymBase + sym_hdr.cbSymOffset)); 1187 1188 for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++) 1189 print_symbol (&l_symbols[symi], 1190 symi - fdp->isymBase, 1191 str_base, 1192 aux_base, 1193 -1, 1194 fdp); 1195 1196 if (want_scope && cur_scope != (scope_t *) 0) 1197 printf ("\n Warning scope does not end at 0!\n"); 1198 1199 /* 1200 * print the aux. table if desired. 1201 */ 1202 1203 if (want_aux && fdp->caux != 0) 1204 { 1205 int auxi; 1206 1207 printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n", 1208 (ulong) fdp->caux, 1209 (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset)); 1210 1211 for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++) 1212 print_aux (aux_base[auxi], auxi, used_base[auxi]); 1213 } 1214 1215 /* 1216 * print the relative file descriptors. 1217 */ 1218 if (want_rfd && fdp->crfd != 0) 1219 { 1220 ulong *rfd_ptr, i; 1221 1222 printf ("\n There are %lu relative file descriptors, starting at %lu.\n", 1223 (ulong) fdp->crfd, 1224 (ulong) fdp->rfdBase); 1225 1226 rfd_ptr = rfile_desc + fdp->rfdBase; 1227 for (i = 0; i < (ulong) fdp->crfd; i++) 1228 { 1229 printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr); 1230 rfd_ptr++; 1231 } 1232 } 1233 1234 /* 1235 * do the procedure descriptors. 1236 */ 1237 printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd); 1238 printf ("starting at %lu.\n", (ulong) fdp->ipdFirst); 1239 1240 for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++) 1241 { 1242 PDR *proc_ptr = &proc_desc[pdi]; 1243 printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst)); 1244 1245 if (l_symbols != 0) 1246 printf ("\t Name index = %-11ld Name = \"%s\"\n", 1247 (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss, 1248 l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base); 1249 1250 printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n", 1251 (long) proc_ptr->regmask, 1252 (long) proc_ptr->regoffset, 1253 (long) proc_ptr->fregmask, 1254 (long) proc_ptr->fregoffset); 1255 1256 printf ("\t .frame $%d,%ld,$%d\n", 1257 (int) proc_ptr->framereg, 1258 (long) proc_ptr->frameoffset, 1259 (int) proc_ptr->pcreg); 1260 1261 printf ("\t Opt. start = %-11ld Symbols start = %ld\n", 1262 (long) proc_ptr->iopt, 1263 (long) proc_ptr->isym); 1264 1265 printf ("\t First line # = %-11ld Last line # = %ld\n", 1266 (long) proc_ptr->lnLow, 1267 (long) proc_ptr->lnHigh); 1268 1269 printf ("\t Line Offset = %-11ld Address = 0x%08lx\n", 1270 (long) proc_ptr->cbLineOffset, 1271 (long) proc_ptr->adr); 1272 1273 /* 1274 * print the line number entries. 1275 */ 1276 1277 if (want_line && fdp->cline != 0) 1278 { 1279 int delta, count; 1280 long cur_line = proc_ptr->lnLow; 1281 uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset 1282 + fdp->cbLineOffset); 1283 uchar *line_end; 1284 1285 if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */ 1286 line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset; 1287 else /* not last proc. */ 1288 line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset 1289 + fdp->cbLineOffset); 1290 1291 printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n", 1292 (ulong) (line_end - line_ptr), 1293 (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset)); 1294 1295 while (line_ptr < line_end) 1296 { /* sign extend nibble */ 1297 delta = ((*line_ptr >> 4) ^ 0x8) - 0x8; 1298 count = (*line_ptr & 0xf) + 1; 1299 if (delta != -8) 1300 line_ptr++; 1301 else 1302 { 1303 delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff); 1304 delta = (delta ^ 0x8000) - 0x8000; 1305 line_ptr += 3; 1306 } 1307 1308 cur_line += delta; 1309 printf ("\t Line %11ld, delta %5d, count %2d\n", 1310 cur_line, 1311 delta, 1312 count); 1313 } 1314 } 1315 } 1316} 1317 1318 1319/* Read in the portions of the .T file that we will print out. */ 1320 1321static void 1322read_tfile (void) 1323{ 1324 short magic; 1325 off_t sym_hdr_offset = 0; 1326 1327 read_seek (&magic, sizeof (magic), 0, "Magic number"); 1328 if (!tfile) 1329 { 1330 /* Print out the global header, since this is not a T-file. */ 1331 1332 read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header"); 1333 1334 print_global_hdr (&global_hdr); 1335 1336 if (global_hdr.f_symptr == 0) 1337 { 1338 printf ("No symbolic header, Goodbye!\n"); 1339 exit (1); 1340 } 1341 1342 sym_hdr_offset = global_hdr.f_symptr; 1343 } 1344 1345 read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header"); 1346 1347 print_sym_hdr (&sym_hdr); 1348 1349 lines = read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset, 1350 "Line numbers"); 1351 1352 dense_nums = read_seek (NULL, sym_hdr.idnMax * sizeof (DNR), 1353 sym_hdr.cbDnOffset, "Dense numbers"); 1354 1355 proc_desc = read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR), 1356 sym_hdr.cbPdOffset, "Procedure tables"); 1357 1358 l_symbols = read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR), 1359 sym_hdr.cbSymOffset, "Local symbols"); 1360 1361 opt_symbols = read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR), 1362 sym_hdr.cbOptOffset, "Optimization symbols"); 1363 1364 aux_symbols = read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU), 1365 sym_hdr.cbAuxOffset, "Auxiliary symbols"); 1366 1367 if (sym_hdr.iauxMax > 0) 1368 aux_used = xcalloc (sym_hdr.iauxMax, 1); 1369 1370 l_strings = read_seek (NULL, sym_hdr.issMax, 1371 sym_hdr.cbSsOffset, "Local string table"); 1372 1373 e_strings = read_seek (NULL, sym_hdr.issExtMax, 1374 sym_hdr.cbSsExtOffset, "External string table"); 1375 1376 file_desc = read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR), 1377 sym_hdr.cbFdOffset, "File tables"); 1378 1379 rfile_desc = read_seek (NULL, sym_hdr.crfd * sizeof (ulong), 1380 sym_hdr.cbRfdOffset, "Relative file tables"); 1381 1382 e_symbols = read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR), 1383 sym_hdr.cbExtOffset, "External symbols"); 1384} 1385 1386 1387 1388extern int main (int, char **); 1389 1390int 1391main (int argc, char **argv) 1392{ 1393 int i, opt; 1394 1395 /* 1396 * Process arguments 1397 */ 1398 while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1) 1399 switch (opt) 1400 { 1401 default: errors++; break; 1402 case 'a': want_aux++; break; /* print aux table */ 1403 case 'l': want_line++; break; /* print line numbers */ 1404 case 'r': want_rfd++; break; /* print relative fd's */ 1405 case 's': want_scope++; break; /* print scope info */ 1406 case 'v': verbose++; break; /* print version # */ 1407 case 'V': version++; break; /* print version # */ 1408 case 't': tfile++; break; /* this is a tfile (without header), 1409 and not a .o */ 1410 } 1411 1412 if (version) 1413 { 1414 printf ("mips-tdump (GCC) %s\n", version_string); 1415 fputs ("Copyright (C) 2006 Free Software Foundation, Inc.\n", stdout); 1416 fputs ("This is free software; see the source for copying conditions. There is NO\n\ 1417warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n", 1418 stdout); 1419 exit (0); 1420 } 1421 1422 if (optind != argc - 1) 1423 errors++; 1424 1425 if (verbose || errors) 1426 { 1427 fprintf (stderr, "mips-tdump (GCC) %s", version_string); 1428#ifdef TARGET_VERSION 1429 TARGET_VERSION; 1430#endif 1431 fputc ('\n', stderr); 1432 } 1433 1434 if (errors) 1435 { 1436 fprintf (stderr, "Calling Sequence:\n"); 1437 fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]); 1438 fprintf (stderr, "\n"); 1439 fprintf (stderr, "switches:\n"); 1440 fprintf (stderr, "\t-a Print out auxiliary table.\n"); 1441 fprintf (stderr, "\t-l Print out line numbers.\n"); 1442 fprintf (stderr, "\t-r Print out relative file descriptors.\n"); 1443 fprintf (stderr, "\t-s Print out the current scopes for an item.\n"); 1444 fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n"); 1445 fprintf (stderr, "\t-v Print program version.\n"); 1446 return 1; 1447 } 1448 1449 /* 1450 * Open and process the input file. 1451 */ 1452 tfile_fd = open (argv[optind], O_RDONLY); 1453 if (tfile_fd < 0) 1454 { 1455 perror (argv[optind]); 1456 return 1; 1457 } 1458 1459 read_tfile (); 1460 1461 /* 1462 * Print any global aux words if any. 1463 */ 1464 if (want_aux) 1465 { 1466 long last_aux_in_use; 1467 1468 if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0) 1469 { 1470 printf ("\nGlobal auxiliary entries before first file:\n"); 1471 for (i = 0; i < file_desc[0].iauxBase; i++) 1472 print_aux (aux_symbols[i], 0, aux_used[i]); 1473 } 1474 1475 if (sym_hdr.ifdMax == 0) 1476 last_aux_in_use = 0; 1477 else 1478 last_aux_in_use 1479 = (file_desc[sym_hdr.ifdMax-1].iauxBase 1480 + file_desc[sym_hdr.ifdMax-1].caux - 1); 1481 1482 if (last_aux_in_use < sym_hdr.iauxMax-1) 1483 { 1484 printf ("\nGlobal auxiliary entries after last file:\n"); 1485 for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++) 1486 print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]); 1487 } 1488 } 1489 1490 /* 1491 * Print the information for each file. 1492 */ 1493 for (i = 0; i < sym_hdr.ifdMax; i++) 1494 print_file_desc (&file_desc[i], i); 1495 1496 /* 1497 * Print the external symbols. 1498 */ 1499 want_scope = 0; /* scope info is meaning for extern symbols */ 1500 printf ("\nThere are %lu external symbols, starting at %lu\n", 1501 (ulong) sym_hdr.iextMax, 1502 (ulong) sym_hdr.cbExtOffset); 1503 1504 for(i = 0; i < sym_hdr.iextMax; i++) 1505 print_symbol (&e_symbols[i].asym, i, e_strings, 1506 aux_symbols + file_desc[e_symbols[i].ifd].iauxBase, 1507 e_symbols[i].ifd, 1508 &file_desc[e_symbols[i].ifd]); 1509 1510 /* 1511 * Print unused aux symbols now. 1512 */ 1513 1514 if (want_aux) 1515 { 1516 int first_time = 1; 1517 1518 for (i = 0; i < sym_hdr.iauxMax; i++) 1519 { 1520 if (! aux_used[i]) 1521 { 1522 if (first_time) 1523 { 1524 printf ("\nThe following auxiliary table entries were unused:\n\n"); 1525 first_time = 0; 1526 } 1527 1528 printf (" #%-5d %11ld 0x%08lx %s\n", 1529 i, 1530 (long) aux_symbols[i].isym, 1531 (long) aux_symbols[i].isym, 1532 type_to_string (aux_symbols, i, (FDR *) 0)); 1533 } 1534 } 1535 } 1536 1537 return 0; 1538} 1539