mips-tdump.c revision 259563
1339640Smm/* Read and manage MIPS symbol tables from object modules. 2339640Smm Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 3339640Smm 2006 Free Software Foundation, Inc. 4339640Smm Contributed by hartzell@boulder.colorado.edu, 5339640Smm Rewritten by meissner@osf.org. 6339640Smm 7339640SmmThis file is part of GCC. 8339640Smm 9339640SmmGCC is free software; you can redistribute it and/or modify it under 10339640Smmthe terms of the GNU General Public License as published by the Free 11339640SmmSoftware Foundation; either version 2, or (at your option) any later 12339640Smmversion. 13339640Smm 14339640SmmGCC is distributed in the hope that it will be useful, but WITHOUT ANY 15339640SmmWARRANTY; without even the implied warranty of MERCHANTABILITY or 16339640SmmFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17339640Smmfor more details. 18339640Smm 19339640SmmYou should have received a copy of the GNU General Public License 20339640Smmalong with GCC; see the file COPYING. If not, write to the Free 21339640SmmSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 22339640Smm02110-1301, USA. */ 23339640Smm 24339640Smm#include "config.h" 25339640Smm#include "system.h" 26339640Smm#include "coretypes.h" 27348608Smm#include "tm.h" 28339640Smm#include "version.h" 29339640Smm#ifdef index 30339640Smm#undef index 31339640Smm#endif 32339640Smm#ifndef CROSS_DIRECTORY_STRUCTURE 33339640Smm#include <a.out.h> 34339640Smm#else 35339640Smm#include "mips/a.out.h" 36348608Smm#endif /* CROSS_DIRECTORY_STRUCTURE */ 37348608Smm 38348608Smm/* Include getopt.h for the sake of getopt_long. */ 39339640Smm#include "getopt.h" 40339640Smm 41339640Smm#ifndef MIPS_IS_STAB 42339640Smm/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for 43339640Smm and mips-tdump.c to print them out. This is used on the Alpha, 44339640Smm which does not include mips.h. 45339640Smm 46339640Smm These must match the corresponding definitions in gdb/mipsread.c. 47339640Smm Unfortunately, gcc and gdb do not currently share any directories. */ 48339640Smm 49339640Smm#define CODE_MASK 0x8F300 50339640Smm#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK) 51339640Smm#define MIPS_MARK_STAB(code) ((code)+CODE_MASK) 52339640Smm#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK) 53339640Smm#endif 54339640Smm 55339640Smm#define uchar unsigned char 56339640Smm#define ushort unsigned short 57339640Smm#define uint unsigned int 58339640Smm#define ulong unsigned long 59339640Smm 60339640Smm 61339640Smm/* Redefinition of storage classes as an enumeration for better 62339640Smm debugging. */ 63339640Smm 64339640Smm#ifndef stStaParam 65339640Smm#define stStaParam 16 /* Fortran static parameters */ 66358090Smm#endif 67339640Smm 68339640Smm#ifndef btVoid 69339640Smm#define btVoid 26 /* void basic type */ 70339640Smm#endif 71339640Smm 72339640Smmtypedef enum sc { 73339640Smm sc_Nil = scNil, /* no storage class */ 74339640Smm sc_Text = scText, /* text symbol */ 75339640Smm sc_Data = scData, /* initialized data symbol */ 76358090Smm sc_Bss = scBss, /* un-initialized data symbol */ 77339640Smm sc_Register = scRegister, /* value of symbol is register number */ 78339640Smm sc_Abs = scAbs, /* value of symbol is absolute */ 79339640Smm sc_Undefined = scUndefined, /* who knows? */ 80339640Smm sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */ 81339640Smm sc_Bits = scBits, /* this is a bit field */ 82339640Smm sc_CdbSystem = scCdbSystem, /* var's value is IN CDB's address space */ 83358090Smm sc_RegImage = scRegImage, /* register value saved on stack */ 84339746Smm sc_Info = scInfo, /* symbol contains debugger information */ 85339640Smm sc_UserStruct = scUserStruct, /* addr in struct user for current process */ 86348608Smm sc_SData = scSData, /* load time only small data */ 87348608Smm sc_SBss = scSBss, /* load time only small common */ 88348608Smm sc_RData = scRData, /* load time only read only data */ 89348608Smm sc_Var = scVar, /* Var parameter (fortran,pascal) */ 90348608Smm sc_Common = scCommon, /* common variable */ 91339640Smm sc_SCommon = scSCommon, /* small common */ 92348608Smm sc_VarRegister = scVarRegister, /* Var parameter in a register */ 93348608Smm sc_Variant = scVariant, /* Variant record */ 94348608Smm sc_SUndefined = scSUndefined, /* small undefined(external) data */ 95348608Smm sc_Init = scInit, /* .init section symbol */ 96339640Smm sc_Max = scMax /* Max storage class+1 */ 97348608Smm} sc_t; 98348608Smm 99348608Smm/* Redefinition of symbol type. */ 100348608Smm 101339640Smmtypedef enum st { 102348608Smm st_Nil = stNil, /* Nuthin' special */ 103348608Smm st_Global = stGlobal, /* external symbol */ 104348608Smm st_Static = stStatic, /* static */ 105348608Smm st_Param = stParam, /* procedure argument */ 106348608Smm st_Local = stLocal, /* local variable */ 107339640Smm st_Label = stLabel, /* label */ 108348608Smm st_Proc = stProc, /* " " Procedure */ 109348608Smm st_Block = stBlock, /* beginning of block */ 110348608Smm st_End = stEnd, /* end (of anything) */ 111348608Smm st_Member = stMember, /* member (of anything - struct/union/enum */ 112348608Smm st_Typedef = stTypedef, /* type definition */ 113348608Smm st_File = stFile, /* file name */ 114348608Smm st_RegReloc = stRegReloc, /* register relocation */ 115348608Smm st_Forward = stForward, /* forwarding address */ 116348608Smm st_StaticProc = stStaticProc, /* load time only static procs */ 117348608Smm st_StaParam = stStaParam, /* Fortran static parameters */ 118358090Smm st_Constant = stConstant, /* const */ 119358090Smm#ifdef stStruct 120339640Smm st_Struct = stStruct, /* struct */ 121339640Smm st_Union = stUnion, /* union */ 122348608Smm st_Enum = stEnum, /* enum */ 123348608Smm#endif 124348608Smm st_Str = stStr, /* string */ 125348608Smm st_Number = stNumber, /* pure number (i.e. 4 NOR 2+2) */ 126348608Smm st_Expr = stExpr, /* 2+2 vs. 4 */ 127348608Smm st_Type = stType, /* post-coercion SER */ 128348608Smm st_Max = stMax /* max type+1 */ 129348608Smm} st_t; 130348608Smm 131348608Smm/* Redefinition of type qualifiers. */ 132348608Smm 133348608Smmtypedef enum tq { 134348608Smm tq_Nil = tqNil, /* bt is what you see */ 135348608Smm tq_Ptr = tqPtr, /* pointer */ 136348608Smm tq_Proc = tqProc, /* procedure */ 137348608Smm tq_Array = tqArray, /* duh */ 138348608Smm tq_Far = tqFar, /* longer addressing - 8086/8 land */ 139348608Smm tq_Vol = tqVol, /* volatile */ 140348608Smm tq_Max = tqMax /* Max type qualifier+1 */ 141348608Smm} tq_t; 142348608Smm 143348608Smm/* Redefinition of basic types. */ 144348608Smm 145348608Smmtypedef enum bt { 146348608Smm bt_Nil = btNil, /* undefined */ 147348608Smm bt_Adr = btAdr, /* address - integer same size as pointer */ 148348608Smm bt_Char = btChar, /* character */ 149339640Smm bt_UChar = btUChar, /* unsigned character */ 150348608Smm bt_Short = btShort, /* short */ 151348608Smm bt_UShort = btUShort, /* unsigned short */ 152348608Smm bt_Int = btInt, /* int */ 153348608Smm bt_UInt = btUInt, /* unsigned int */ 154348608Smm bt_Long = btLong, /* long */ 155348608Smm bt_ULong = btULong, /* unsigned long */ 156348608Smm bt_Float = btFloat, /* float (real) */ 157348608Smm bt_Double = btDouble, /* Double (real) */ 158348608Smm bt_Struct = btStruct, /* Structure (Record) */ 159348608Smm bt_Union = btUnion, /* Union (variant) */ 160339640Smm bt_Enum = btEnum, /* Enumerated */ 161339640Smm bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */ 162339640Smm bt_Range = btRange, /* subrange of int */ 163348608Smm bt_Set = btSet, /* pascal sets */ 164348608Smm bt_Complex = btComplex, /* fortran complex */ 165348608Smm bt_DComplex = btDComplex, /* fortran double complex */ 166339640Smm bt_Indirect = btIndirect, /* forward or unnamed typedef */ 167348608Smm bt_FixedDec = btFixedDec, /* Fixed Decimal */ 168348608Smm bt_FloatDec = btFloatDec, /* Float Decimal */ 169348608Smm bt_String = btString, /* Varying Length Character String */ 170339640Smm bt_Bit = btBit, /* Aligned Bit String */ 171339640Smm bt_Picture = btPicture, /* Picture */ 172339640Smm bt_Void = btVoid, /* void */ 173348608Smm bt_Max = btMax /* Max basic type+1 */ 174348608Smm} bt_t; 175348608Smm 176348608Smm/* Redefinition of the language codes. */ 177339640Smm 178339640Smmtypedef enum lang { 179339640Smm lang_C = langC, 180348608Smm lang_Pascal = langPascal, 181348608Smm lang_Fortran = langFortran, 182348608Smm lang_Assembler = langAssembler, 183348608Smm lang_Machine = langMachine, 184348608Smm lang_Nil = langNil, 185339640Smm lang_Ada = langAda, 186339640Smm lang_Pl1 = langPl1, 187339640Smm lang_Cobol = langCobol 188348608Smm} lang_t; 189348608Smm 190348608Smm/* Redefinition of the debug level codes. */ 191348608Smm 192348608Smmtypedef enum glevel { 193348608Smm glevel_0 = GLEVEL_0, 194348608Smm glevel_1 = GLEVEL_1, 195339640Smm glevel_2 = GLEVEL_2, 196339640Smm glevel_3 = GLEVEL_3 197339640Smm} glevel_t; 198348608Smm 199348608Smm 200348608Smm/* Keep track of the active scopes. */ 201339640Smmtypedef struct scope { 202348608Smm struct scope *prev; /* previous scope */ 203348608Smm ulong open_sym; /* symbol opening scope */ 204339640Smm sc_t sc; /* storage class */ 205348608Smm st_t st; /* symbol type */ 206348608Smm} scope_t; 207348608Smm 208339640Smmstruct filehdr global_hdr; /* a.out header */ 209348608Smm 210348608Smmint errors = 0; /* # of errors */ 211348608Smmint want_aux = 0; /* print aux table */ 212339640Smmint want_line = 0; /* print line numbers */ 213358090Smmint want_rfd = 0; /* print relative file desc's */ 214339640Smmint want_scope = 0; /* print scopes for every symbol */ 215348608Smmint tfile = 0; /* no global header file */ 216348608Smmint version = 0; /* print version # */ 217348608Smmint verbose = 0; 218348608Smmint tfile_fd; /* file descriptor of .T file */ 219348608Smmoff_t tfile_offset; /* current offset in .T file */ 220348608Smmscope_t *cur_scope = 0; /* list of active scopes */ 221348608Smmscope_t *free_scope = 0; /* list of freed scopes */ 222348608SmmHDRR sym_hdr; /* symbolic header */ 223348608Smmchar *l_strings; /* local strings */ 224348608Smmchar *e_strings; /* external strings */ 225348608SmmSYMR *l_symbols; /* local symbols */ 226348608SmmEXTR *e_symbols; /* external symbols */ 227348608SmmLINER *lines; /* line numbers */ 228348608SmmDNR *dense_nums; /* dense numbers */ 229348608SmmOPTR *opt_symbols; /* optimization symbols */ 230348608SmmAUXU *aux_symbols; /* Auxiliary symbols */ 231348608Smmchar *aux_used; /* map of which aux syms are used */ 232348608SmmFDR *file_desc; /* file tables */ 233348608Smmulong *rfile_desc; /* relative file tables */ 234348608SmmPDR *proc_desc; /* procedure tables */ 235348608Smm 236348608Smm/* Forward reference for functions. */ 237348608Smmstatic void *read_seek (void *, size_t, off_t, const char *); 238339640Smmstatic void read_tfile (void); 239348608Smmstatic void print_global_hdr (struct filehdr *); 240339640Smmstatic void print_sym_hdr (HDRR *); 241339640Smmstatic void print_file_desc (FDR *, int); 242348608Smmstatic void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *); 243339640Smmstatic void print_aux (AUXU, int, int); 244348608Smmstatic void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *); 245339640Smmstatic const char *st_to_string (st_t); 246348608Smmstatic const char *sc_to_string (sc_t); 247339640Smmstatic const char *glevel_to_string (glevel_t); 248348608Smmstatic const char *lang_to_string (lang_t); 249339640Smmstatic const char *type_to_string (AUXU *, int, FDR *); 250348608Smm 251339640Smmextern char *optarg; 252339640Smmextern int optind; 253348608Smmextern int opterr; 254348608Smm 255348608Smm/* Create a table of debugging stab-codes and corresponding names. */ 256348608Smm 257339640Smm#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING}, 258348608Smmconst struct {const short code; const char string[10];} stab_names[] = { 259348608Smm#include "stab.def" 260339640Smm#undef __define_stab 261348608Smm}; 262348608Smm 263339640Smm/* Command line options for getopt_long. */ 264339640Smm 265339640Smmstatic const struct option options[] = 266339640Smm{ 267348608Smm { "version", 0, 0, 'V' }, 268348608Smm { "verbose", 0, 0, 'v' }, 269339640Smm { 0, 0, 0, 0 } 270339640Smm}; 271348608Smm 272348608Smm/* Read some bytes at a specified location, and return a pointer. 273339640Smm Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE 274348608Smm bytes from offset OFFSET. In case of errors CONTEXT is used as 275348608Smm error message. */ 276348608Smm 277348608Smmstatic void * 278348608Smmread_seek (void *ptr, size_t size, off_t offset, const char *context) 279348608Smm{ 280348608Smm long read_size = 0; 281348608Smm 282348608Smm if (size == 0) /* nothing to read */ 283339640Smm return ptr; 284339640Smm 285339640Smm if (!ptr) 286339640Smm ptr = xmalloc (size); 287348608Smm 288348608Smm if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1) 289339640Smm || (read_size = read (tfile_fd, ptr, size)) < 0) 290348608Smm { 291348608Smm perror (context); 292348608Smm exit (1); 293348608Smm } 294339640Smm 295348608Smm if (read_size != (long) size) 296339640Smm { 297339640Smm fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n", 298339640Smm context, read_size, (long) size); 299348608Smm exit (1); 300348608Smm } 301348608Smm 302348608Smm tfile_offset = offset + size; 303348608Smm return ptr; 304339640Smm} 305339640Smm 306339640Smm 307348608Smm/* Convert language code to string format. */ 308348608Smm 309339640Smmstatic const char * 310339640Smmlang_to_string (lang_t lang) 311339640Smm{ 312339640Smm switch (lang) 313348608Smm { 314339640Smm case langC: return "C"; 315348608Smm case langPascal: return "Pascal"; 316348608Smm case langFortran: return "Fortran"; 317348608Smm case langAssembler: return "Assembler"; 318339640Smm case langMachine: return "Machine"; 319348608Smm case langNil: return "Nil"; 320348608Smm case langAda: return "Ada"; 321348608Smm case langPl1: return "Pl1"; 322348608Smm case langCobol: return "Cobol"; 323348608Smm } 324339640Smm 325348608Smm return "Unknown language"; 326348608Smm} 327348608Smm 328348608Smm 329348608Smm/* Convert storage class to string. */ 330348608Smm 331339640Smmstatic const char * 332348608Smmsc_to_string (sc_t storage_class) 333348608Smm{ 334348608Smm switch(storage_class) 335348608Smm { 336348608Smm case sc_Nil: return "Nil"; 337339640Smm case sc_Text: return "Text"; 338348608Smm case sc_Data: return "Data"; 339348608Smm case sc_Bss: return "Bss"; 340348608Smm case sc_Register: return "Register"; 341348608Smm case sc_Abs: return "Abs"; 342348608Smm case sc_Undefined: return "Undefined"; 343339640Smm case sc_CdbLocal: return "CdbLocal"; 344348608Smm case sc_Bits: return "Bits"; 345348608Smm case sc_CdbSystem: return "CdbSystem"; 346348608Smm case sc_RegImage: return "RegImage"; 347348608Smm case sc_Info: return "Info"; 348348608Smm case sc_UserStruct: return "UserStruct"; 349348608Smm case sc_SData: return "SData"; 350348608Smm case sc_SBss: return "SBss"; 351348608Smm case sc_RData: return "RData"; 352348608Smm case sc_Var: return "Var"; 353348608Smm case sc_Common: return "Common"; 354348608Smm case sc_SCommon: return "SCommon"; 355339640Smm case sc_VarRegister: return "VarRegister"; 356339640Smm case sc_Variant: return "Variant"; 357339640Smm case sc_SUndefined: return "SUndefined"; 358339640Smm case sc_Init: return "Init"; 359358090Smm case sc_Max: return "Max"; 360339640Smm } 361339640Smm 362339640Smm return "???"; 363348608Smm} 364339640Smm 365339640Smm 366339640Smm/* Convert symbol type to string. */ 367348608Smm 368339640Smmstatic const char * 369339640Smmst_to_string (st_t symbol_type) 370339640Smm{ 371339640Smm switch(symbol_type) 372348608Smm { 373348608Smm case st_Nil: return "Nil"; 374348608Smm case st_Global: return "Global"; 375339640Smm case st_Static: return "Static"; 376339640Smm case st_Param: return "Param"; 377339640Smm case st_Local: return "Local"; 378339640Smm case st_Label: return "Label"; 379339640Smm case st_Proc: return "Proc"; 380339640Smm case st_Block: return "Block"; 381348608Smm case st_End: return "End"; 382348608Smm case st_Member: return "Member"; 383339640Smm case st_Typedef: return "Typedef"; 384348608Smm case st_File: return "File"; 385348608Smm case st_RegReloc: return "RegReloc"; 386339640Smm case st_Forward: return "Forward"; 387358090Smm case st_StaticProc: return "StaticProc"; 388348608Smm case st_Constant: return "Constant"; 389339640Smm case st_StaParam: return "StaticParam"; 390348608Smm#ifdef stStruct 391348608Smm case st_Struct: return "Struct"; 392339640Smm case st_Union: return "Union"; 393348608Smm case st_Enum: return "Enum"; 394339640Smm#endif 395339640Smm case st_Str: return "String"; 396339640Smm case st_Number: return "Number"; 397339640Smm case st_Expr: return "Expr"; 398348608Smm case st_Type: return "Type"; 399339640Smm case st_Max: return "Max"; 400339640Smm } 401339640Smm 402339640Smm return "???"; 403339640Smm} 404339640Smm 405348608Smm 406339640Smm/* Convert debug level to string. */ 407339640Smm 408339640Smmstatic const char * 409339640Smmglevel_to_string (glevel_t g_level) 410339640Smm{ 411348608Smm switch(g_level) 412348608Smm { 413348608Smm case GLEVEL_0: return "G0"; 414348608Smm case GLEVEL_1: return "G1"; 415348608Smm case GLEVEL_2: return "G2"; 416339640Smm case GLEVEL_3: return "G3"; 417339640Smm } 418339640Smm 419339640Smm return "??"; 420339640Smm} 421348608Smm 422348608Smm 423339640Smm/* Convert the type information to string format. */ 424348608Smm 425348608Smmstatic const char * 426339640Smmtype_to_string (AUXU *aux_ptr, int index, FDR *fdp) 427348608Smm{ 428348608Smm AUXU u; 429348608Smm struct qual { 430339640Smm tq_t type; 431348608Smm int low_bound; 432339640Smm int high_bound; 433339640Smm int stride; 434339640Smm } qualifiers[7]; 435339640Smm 436339640Smm bt_t basic_type; 437348608Smm int i; 438348608Smm static char buffer1[1024]; 439348608Smm static char buffer2[1024]; 440339640Smm char *p1 = buffer1; 441339640Smm char *p2 = buffer2; 442348608Smm char *used_ptr = aux_used + (aux_ptr - aux_symbols); 443339640Smm 444339640Smm for (i = 0; i < 7; i++) 445348608Smm { 446348608Smm qualifiers[i].low_bound = 0; 447339640Smm qualifiers[i].high_bound = 0; 448348608Smm qualifiers[i].stride = 0; 449348608Smm } 450339640Smm 451348608Smm used_ptr[index] = 1; 452348608Smm u = aux_ptr[index++]; 453339640Smm if (u.isym == -1) 454339640Smm return "-1 (no type)"; 455348608Smm 456339640Smm basic_type = (bt_t) u.ti.bt; 457348608Smm qualifiers[0].type = (tq_t) u.ti.tq0; 458339640Smm qualifiers[1].type = (tq_t) u.ti.tq1; 459339640Smm qualifiers[2].type = (tq_t) u.ti.tq2; 460348608Smm qualifiers[3].type = (tq_t) u.ti.tq3; 461339640Smm qualifiers[4].type = (tq_t) u.ti.tq4; 462348608Smm qualifiers[5].type = (tq_t) u.ti.tq5; 463339640Smm qualifiers[6].type = tq_Nil; 464339640Smm 465348608Smm /* 466348608Smm * Go get the basic type. 467348608Smm */ 468339640Smm switch (basic_type) 469348608Smm { 470348608Smm case bt_Nil: /* undefined */ 471339640Smm strcpy (p1, "nil"); 472348608Smm break; 473348608Smm 474339640Smm case bt_Adr: /* address - integer same size as pointer */ 475348608Smm strcpy (p1, "address"); 476339640Smm break; 477348608Smm 478348608Smm case bt_Char: /* character */ 479348608Smm strcpy (p1, "char"); 480348608Smm break; 481339640Smm 482339640Smm case bt_UChar: /* unsigned character */ 483348608Smm strcpy (p1, "unsigned char"); 484348608Smm break; 485348608Smm 486348608Smm case bt_Short: /* short */ 487348608Smm strcpy (p1, "short"); 488348608Smm break; 489348608Smm 490348608Smm case bt_UShort: /* unsigned short */ 491348608Smm strcpy (p1, "unsigned short"); 492348608Smm break; 493348608Smm 494348608Smm case bt_Int: /* int */ 495348608Smm strcpy (p1, "int"); 496348608Smm break; 497348608Smm 498339640Smm case bt_UInt: /* unsigned int */ 499348608Smm strcpy (p1, "unsigned int"); 500339640Smm break; 501339640Smm 502348608Smm case bt_Long: /* long */ 503348608Smm strcpy (p1, "long"); 504348608Smm break; 505348608Smm 506348608Smm case bt_ULong: /* unsigned long */ 507348608Smm strcpy (p1, "unsigned long"); 508348608Smm break; 509339640Smm 510348608Smm case bt_Float: /* float (real) */ 511348608Smm strcpy (p1, "float"); 512348608Smm break; 513348608Smm 514348608Smm case bt_Double: /* Double (real) */ 515348608Smm strcpy (p1, "double"); 516339640Smm break; 517339640Smm 518348608Smm /* Structures add 1-2 aux words: 519348608Smm 1st word is [ST_RFDESCAPE, offset] pointer to struct def; 520348608Smm 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 521348608Smm 522339640Smm case bt_Struct: /* Structure (Record) */ 523339640Smm emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp); 524339640Smm used_ptr[index] = 1; 525348608Smm if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 526339640Smm used_ptr[++index] = 1; 527348608Smm 528339640Smm index++; /* skip aux words */ 529339640Smm break; 530339640Smm 531339640Smm /* Unions add 1-2 aux words: 532348608Smm 1st word is [ST_RFDESCAPE, offset] pointer to union def; 533348608Smm 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 534339640Smm 535348608Smm case bt_Union: /* Union */ 536348608Smm emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp); 537348608Smm used_ptr[index] = 1; 538339640Smm if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 539348608Smm used_ptr[++index] = 1; 540348608Smm 541339640Smm index++; /* skip aux words */ 542339640Smm break; 543339640Smm 544348608Smm /* Enumerations add 1-2 aux words: 545348608Smm 1st word is [ST_RFDESCAPE, offset] pointer to enum def; 546339640Smm 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ 547348608Smm 548348608Smm case bt_Enum: /* Enumeration */ 549348608Smm emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp); 550348608Smm used_ptr[index] = 1; 551348608Smm if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE) 552348608Smm used_ptr[++index] = 1; 553348608Smm 554339640Smm index++; /* skip aux words */ 555348608Smm break; 556348608Smm 557348608Smm case bt_Typedef: /* defined via a typedef, isymRef points */ 558339640Smm strcpy (p1, "typedef"); 559348608Smm break; 560348608Smm 561348608Smm case bt_Range: /* subrange of int */ 562348608Smm strcpy (p1, "subrange"); 563348608Smm break; 564339640Smm 565348608Smm case bt_Set: /* pascal sets */ 566339640Smm strcpy (p1, "set"); 567339640Smm break; 568339640Smm 569348608Smm case bt_Complex: /* fortran complex */ 570339640Smm strcpy (p1, "complex"); 571348608Smm break; 572348608Smm 573339640Smm case bt_DComplex: /* fortran double complex */ 574348608Smm strcpy (p1, "double complex"); 575348608Smm break; 576348608Smm 577348608Smm case bt_Indirect: /* forward or unnamed typedef */ 578339640Smm strcpy (p1, "forward/unnamed typedef"); 579348608Smm break; 580348608Smm 581348608Smm case bt_FixedDec: /* Fixed Decimal */ 582348608Smm strcpy (p1, "fixed decimal"); 583339640Smm break; 584348608Smm 585348608Smm case bt_FloatDec: /* Float Decimal */ 586348608Smm strcpy (p1, "float decimal"); 587348608Smm break; 588348608Smm 589339640Smm case bt_String: /* Varying Length Character String */ 590348608Smm strcpy (p1, "string"); 591348608Smm break; 592339640Smm 593348608Smm case bt_Bit: /* Aligned Bit String */ 594348608Smm strcpy (p1, "bit"); 595348608Smm break; 596339640Smm 597348608Smm case bt_Picture: /* Picture */ 598348608Smm strcpy (p1, "picture"); 599348608Smm break; 600348608Smm 601348608Smm case bt_Void: /* Void */ 602348608Smm strcpy (p1, "void"); 603348608Smm break; 604348608Smm 605348608Smm default: 606348608Smm sprintf (p1, "Unknown basic type %d", (int) basic_type); 607348608Smm break; 608348608Smm } 609339640Smm 610348608Smm p1 += strlen (buffer1); 611348608Smm 612348608Smm /* 613339640Smm * If this is a bitfield, get the bitsize. 614348608Smm */ 615339640Smm if (u.ti.fBitfield) 616339640Smm { 617339640Smm int bitsize; 618348608Smm 619348608Smm used_ptr[index] = 1; 620339640Smm bitsize = aux_ptr[index++].width; 621348608Smm sprintf (p1, " : %d", bitsize); 622348608Smm p1 += strlen (buffer1); 623348608Smm } 624348608Smm 625339640Smm 626348608Smm /* 627348608Smm * Deal with any qualifiers. 628348608Smm */ 629349901Smm if (qualifiers[0].type != tq_Nil) 630339640Smm { 631349901Smm /* 632348608Smm * Snarf up any array bounds in the correct order. Arrays 633348608Smm * store 5 successive words in the aux. table: 634348608Smm * word 0 RNDXR to type of the bounds (i.e., int) 635348608Smm * word 1 Current file descriptor index 636339640Smm * word 2 low bound 637348608Smm * word 3 high bound (or -1 if []) 638348608Smm * word 4 stride size in bits 639348608Smm */ 640348608Smm for (i = 0; i < 7; i++) 641348608Smm { 642339640Smm if (qualifiers[i].type == tq_Array) 643348608Smm { 644339640Smm qualifiers[i].low_bound = aux_ptr[index+2].dnLow; 645339640Smm qualifiers[i].high_bound = aux_ptr[index+3].dnHigh; 646339640Smm qualifiers[i].stride = aux_ptr[index+4].width; 647348608Smm used_ptr[index] = 1; 648348608Smm used_ptr[index+1] = 1; 649339640Smm used_ptr[index+2] = 1; 650348608Smm used_ptr[index+3] = 1; 651339640Smm used_ptr[index+4] = 1; 652348608Smm index += 5; 653348608Smm } 654348608Smm } 655348608Smm 656348608Smm /* 657348608Smm * Now print out the qualifiers. 658339640Smm */ 659348608Smm for (i = 0; i < 6; i++) 660348608Smm { 661348608Smm switch (qualifiers[i].type) 662348608Smm { 663339640Smm case tq_Nil: 664348608Smm case tq_Max: 665348608Smm break; 666348608Smm 667348608Smm case tq_Ptr: 668348608Smm strcpy (p2, "ptr to "); 669348608Smm p2 += sizeof ("ptr to ")-1; 670339640Smm break; 671348608Smm 672348608Smm case tq_Vol: 673348608Smm strcpy (p2, "volatile "); 674339640Smm p2 += sizeof ("volatile ")-1; 675348608Smm break; 676348608Smm 677348608Smm case tq_Far: 678348608Smm strcpy (p2, "far "); 679348608Smm p2 += sizeof ("far ")-1; 680348608Smm break; 681339640Smm 682348608Smm case tq_Proc: 683348608Smm strcpy (p2, "func. ret. "); 684348608Smm p2 += sizeof ("func. ret. "); 685348608Smm break; 686339640Smm 687348608Smm case tq_Array: 688348608Smm { 689348608Smm int first_array = i; 690348608Smm int j; 691348608Smm 692339640Smm /* Print array bounds reversed (i.e., in the order the C 693348608Smm programmer writes them). C is such a fun language.... */ 694348608Smm 695339640Smm while (i < 5 && qualifiers[i+1].type == tq_Array) 696348608Smm i++; 697348608Smm 698339640Smm for (j = i; j >= first_array; j--) 699339640Smm { 700339640Smm strcpy (p2, "array ["); 701339640Smm p2 += sizeof ("array [")-1; 702339640Smm if (qualifiers[j].low_bound != 0) 703339640Smm sprintf (p2, 704339640Smm "%ld:%ld {%ld bits}", 705348608Smm (long) qualifiers[j].low_bound, 706339640Smm (long) qualifiers[j].high_bound, 707348608Smm (long) qualifiers[j].stride); 708348608Smm 709348608Smm else if (qualifiers[j].high_bound != -1) 710339640Smm sprintf (p2, 711348608Smm "%ld {%ld bits}", 712348608Smm (long) (qualifiers[j].high_bound + 1), 713339640Smm (long) (qualifiers[j].stride)); 714348608Smm 715348608Smm else 716348608Smm sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride)); 717348608Smm 718339640Smm p2 += strlen (p2); 719348608Smm strcpy (p2, "] of "); 720348608Smm p2 += sizeof ("] of ")-1; 721348608Smm } 722348608Smm } 723348608Smm break; 724348608Smm } 725339640Smm } 726348608Smm } 727348608Smm 728348608Smm strcpy (p2, buffer1); 729339640Smm return buffer2; 730348608Smm} 731348608Smm 732348608Smm 733339640Smm/* Print out the global file header for object files. */ 734348608Smm 735348608Smmstatic void 736348608Smmprint_global_hdr (struct filehdr *ptr) 737348608Smm{ 738348608Smm char *time = ctime ((time_t *)&ptr->f_timdat); 739348608Smm ushort flags = ptr->f_flags; 740348608Smm 741339640Smm printf("Global file header:\n"); 742348608Smm printf(" %-*s 0x%x\n", 24, "magic number", (ushort) ptr->f_magic); 743348608Smm printf(" %-*s %d\n", 24, "# sections", (int) ptr->f_nscns); 744339640Smm printf(" %-*s %ld, %s", 24, "timestamp", (long) ptr->f_timdat, time); 745339640Smm printf(" %-*s %ld\n", 24, "symbolic header offset", (long) ptr->f_symptr); 746348608Smm printf(" %-*s %ld\n", 24, "symbolic header size", (long) ptr->f_nsyms); 747339640Smm printf(" %-*s %ld\n", 24, "optional header", (long) ptr->f_opthdr); 748339640Smm printf(" %-*s 0x%x", 24, "flags", (ushort) flags); 749348608Smm 750339640Smm if ((flags & F_RELFLG) != 0) 751348608Smm printf (", F_RELFLG"); 752339640Smm 753339640Smm if ((flags & F_EXEC) != 0) 754339640Smm printf (", F_EXEC"); 755348608Smm 756348608Smm if ((flags & F_LNNO) != 0) 757348608Smm printf (", F_LNNO"); 758339640Smm 759348608Smm if ((flags & F_LSYMS) != 0) 760339640Smm printf (", F_LSYMS"); 761348608Smm 762348608Smm if ((flags & F_MINMAL) != 0) 763348608Smm printf (", F_MINMAL"); 764348608Smm 765348608Smm if ((flags & F_UPDATE) != 0) 766348608Smm printf (", F_UPDATE"); 767348608Smm 768348608Smm if ((flags & F_SWABD) != 0) 769348608Smm printf (", F_SWABD"); 770348608Smm 771348608Smm if ((flags & F_AR16WR) != 0) 772348608Smm printf (", F_AR16WR"); 773348608Smm 774348608Smm if ((flags & F_AR32WR) != 0) 775348608Smm printf (", F_AR32WR"); 776348608Smm 777348608Smm if ((flags & F_AR32W) != 0) 778348608Smm printf (", F_AR32W"); 779348608Smm 780339640Smm if ((flags & F_PATCH) != 0) 781348608Smm printf (", F_PATCH/F_NODF"); 782348608Smm 783348608Smm printf ("\n\n"); 784348608Smm} 785348608Smm 786339640Smm 787348608Smm/* Print out the symbolic header. */ 788348608Smm 789348608Smmstatic void 790348608Smmprint_sym_hdr (HDRR *sym_ptr) 791348608Smm{ 792348608Smm int width = 20; 793348608Smm 794348608Smm printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n", 795339640Smm sym_ptr->magic & 0xffff, 796348608Smm (sym_ptr->vstamp & 0xffff) >> 8, 797348608Smm sym_ptr->vstamp & 0xff); 798348608Smm 799348608Smm printf(" %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes"); 800348608Smm printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n"); 801339640Smm 802348608Smm printf(" %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers", 803348608Smm (long) sym_ptr->cbLineOffset, 804339640Smm (long) sym_ptr->cbLine, 805339640Smm (long) sym_ptr->cbLine, 806339640Smm (int) sym_ptr->ilineMax); 807348608Smm 808339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Dense numbers", 809348608Smm (long) sym_ptr->cbDnOffset, 810348608Smm (long) sym_ptr->idnMax, 811348608Smm (long) (sym_ptr->idnMax * sizeof (DNR))); 812348608Smm 813339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Procedures Tables", 814339640Smm (long) sym_ptr->cbPdOffset, 815348608Smm (long) sym_ptr->ipdMax, 816348608Smm (long) (sym_ptr->ipdMax * sizeof (PDR))); 817348608Smm 818339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Local Symbols", 819348608Smm (long) sym_ptr->cbSymOffset, 820348608Smm (long) sym_ptr->isymMax, 821339640Smm (long) (sym_ptr->isymMax * sizeof (SYMR))); 822348608Smm 823348608Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols", 824339640Smm (long) sym_ptr->cbOptOffset, 825339640Smm (long) sym_ptr->ioptMax, 826339640Smm (long) (sym_ptr->ioptMax * sizeof (OPTR))); 827348608Smm 828339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols", 829348608Smm (long) sym_ptr->cbAuxOffset, 830348608Smm (long) sym_ptr->iauxMax, 831348608Smm (long) (sym_ptr->iauxMax * sizeof (AUXU))); 832348608Smm 833339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Local Strings", 834348608Smm (long) sym_ptr->cbSsOffset, 835348608Smm (long) sym_ptr->issMax, 836348608Smm (long) sym_ptr->issMax); 837348608Smm 838339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "External Strings", 839348608Smm (long) sym_ptr->cbSsExtOffset, 840348608Smm (long) sym_ptr->issExtMax, 841348608Smm (long) sym_ptr->issExtMax); 842348608Smm 843339640Smm printf(" %-*s %11ld %11ld %11ld\n", width, "File Tables", 844348608Smm (long) sym_ptr->cbFdOffset, 845339640Smm (long) sym_ptr->ifdMax, 846348608Smm (long) (sym_ptr->ifdMax * sizeof (FDR))); 847348608Smm 848348608Smm printf(" %-*s %11ld %11ld %11ld\n", width, "Relative Files", 849339640Smm (long) sym_ptr->cbRfdOffset, 850339640Smm (long) sym_ptr->crfd, 851339640Smm (long) (sym_ptr->crfd * sizeof (ulong))); 852348608Smm 853348608Smm printf(" %-*s %11ld %11ld %11ld\n", width, "External Symbols", 854339640Smm (long) sym_ptr->cbExtOffset, 855348608Smm (long) sym_ptr->iextMax, 856348608Smm (long) (sym_ptr->iextMax * sizeof (EXTR))); 857348608Smm} 858348608Smm 859348608Smm 860339640Smm/* Print out a symbol. */ 861348608Smm 862348608Smmstatic void 863348608Smmprint_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base, 864339640Smm int ifd, FDR *fdp) 865348608Smm{ 866348608Smm sc_t storage_class = (sc_t) sym_ptr->sc; 867348608Smm st_t symbol_type = (st_t) sym_ptr->st; 868348608Smm ulong index = sym_ptr->index; 869339640Smm char *used_ptr = aux_used + (aux_base - aux_symbols); 870339640Smm scope_t *scope_ptr; 871339640Smm 872348608Smm printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase); 873339640Smm 874348608Smm if (aux_base != (AUXU *) 0 && index != indexNil) 875348608Smm switch (symbol_type) 876348608Smm { 877339640Smm case st_Nil: 878348608Smm case st_Label: 879339640Smm break; 880339640Smm 881339640Smm case st_File: 882348608Smm case st_Block: 883339640Smm printf (" End+1 symbol: %ld\n", index); 884358090Smm if (want_scope) 885348608Smm { 886348608Smm if (free_scope == (scope_t *) 0) 887339640Smm scope_ptr = xmalloc (sizeof (scope_t)); 888348608Smm else 889348608Smm { 890348608Smm scope_ptr = free_scope; 891348608Smm free_scope = scope_ptr->prev; 892339640Smm } 893348608Smm scope_ptr->open_sym = number; 894339640Smm scope_ptr->st = symbol_type; 895339640Smm scope_ptr->sc = storage_class; 896339640Smm scope_ptr->prev = cur_scope; 897348608Smm cur_scope = scope_ptr; 898339640Smm } 899348608Smm break; 900348608Smm 901348608Smm case st_End: 902339640Smm if (storage_class == sc_Text || storage_class == sc_Info) 903348608Smm printf (" First symbol: %ld\n", index); 904339640Smm else 905339640Smm { 906339640Smm used_ptr[index] = 1; 907339640Smm printf (" First symbol: %ld\n", (long) aux_base[index].isym); 908339640Smm } 909339640Smm 910339640Smm if (want_scope) 911339640Smm { 912339640Smm if (cur_scope == (scope_t *) 0) 913339640Smm printf (" Can't pop end scope\n"); 914339640Smm else 915339640Smm { 916339640Smm scope_ptr = cur_scope; 917339640Smm cur_scope = scope_ptr->prev; 918339640Smm scope_ptr->prev = free_scope; 919339640Smm free_scope = scope_ptr; 920339640Smm } 921339640Smm } 922339640Smm break; 923339640Smm 924348608Smm case st_Proc: 925339640Smm case st_StaticProc: 926348608Smm if (MIPS_IS_STAB(sym_ptr)) 927348608Smm ; 928348608Smm else if (ifd == -1) /* local symbol */ 929348608Smm { 930339640Smm used_ptr[index] = used_ptr[index+1] = 1; 931348608Smm printf (" End+1 symbol: %-7ld Type: %s\n", 932348608Smm (long) aux_base[index].isym, 933348608Smm type_to_string (aux_base, index+1, fdp)); 934348608Smm } 935348608Smm else /* global symbol */ 936339640Smm printf (" Local symbol: %ld\n", index); 937348608Smm 938348608Smm if (want_scope) 939339640Smm { 940348608Smm if (free_scope == (scope_t *) 0) 941348608Smm scope_ptr = xmalloc (sizeof (scope_t)); 942348608Smm else 943339640Smm { 944348608Smm scope_ptr = free_scope; 945348608Smm free_scope = scope_ptr->prev; 946348608Smm } 947348608Smm scope_ptr->open_sym = number; 948348608Smm scope_ptr->st = symbol_type; 949348608Smm scope_ptr->sc = storage_class; 950348608Smm scope_ptr->prev = cur_scope; 951348608Smm cur_scope = scope_ptr; 952339640Smm } 953348608Smm break; 954348608Smm 955348608Smm#ifdef stStruct 956348608Smm case st_Struct: 957348608Smm case st_Union: 958348608Smm case st_Enum: 959348608Smm printf (" End+1 symbol: %lu\n", index); 960348608Smm break; 961348608Smm#endif 962348608Smm 963348608Smm default: 964348608Smm if (!MIPS_IS_STAB (sym_ptr)) 965348608Smm { 966348608Smm used_ptr[index] = 1; 967348608Smm printf (" Type: %s\n", 968348608Smm type_to_string (aux_base, index, fdp)); 969348608Smm } 970339640Smm break; 971348608Smm } 972348608Smm 973348608Smm if (want_scope) 974348608Smm { 975339640Smm printf (" Scopes: "); 976348608Smm if (cur_scope == (scope_t *) 0) 977348608Smm printf (" none\n"); 978348608Smm else 979348608Smm { 980348608Smm for (scope_ptr = cur_scope; 981348608Smm scope_ptr != (scope_t *) 0; 982339640Smm scope_ptr = scope_ptr->prev) 983348608Smm { 984348608Smm const char *class; 985348608Smm if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc) 986348608Smm class = "func."; 987348608Smm else if (scope_ptr->st == st_File) 988348608Smm class = "file"; 989348608Smm else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text) 990339640Smm class = "block"; 991348608Smm else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info) 992339640Smm class = "type"; 993339640Smm else 994339640Smm class = "???"; 995348608Smm 996339640Smm printf (" %ld [%s]", scope_ptr->open_sym, class); 997348608Smm } 998348608Smm printf ("\n"); 999339640Smm } 1000348608Smm } 1001348608Smm 1002339640Smm printf (" Value: %-13ld ", 1003348608Smm (long)sym_ptr->value); 1004348608Smm if (ifd == -1) 1005348608Smm printf ("String index: %ld\n", (long)sym_ptr->iss); 1006339640Smm else 1007348608Smm printf ("String index: %-11ld Ifd: %d\n", 1008348608Smm (long)sym_ptr->iss, ifd); 1009348608Smm 1010348608Smm printf (" Symbol type: %-11sStorage class: %-11s", 1011339640Smm st_to_string (symbol_type), sc_to_string (storage_class)); 1012348608Smm 1013339640Smm if (MIPS_IS_STAB(sym_ptr)) 1014339640Smm { 1015339640Smm int i = ARRAY_SIZE (stab_names); 1016348608Smm const char *stab_name = "stab"; 1017348608Smm short code = MIPS_UNMARK_STAB(sym_ptr->index); 1018348608Smm 1019348608Smm while (--i >= 0) 1020348608Smm if (stab_names[i].code == code) 1021348608Smm { 1022348608Smm stab_name = stab_names[i].string; 1023348608Smm break; 1024339640Smm } 1025339640Smm printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name); 1026339640Smm } 1027348608Smm else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil) 1028348608Smm printf ("Index: %ld (line#)\n", (long)sym_ptr->index); 1029348608Smm else 1030348608Smm printf ("Index: %ld\n", (long)sym_ptr->index); 1031348608Smm 1032348608Smm} 1033339640Smm 1034339640Smm 1035339640Smm/* Print out a word from the aux. table in various formats. */ 1036348608Smm 1037348608Smmstatic void 1038348608Smmprint_aux (AUXU u, int auxi, int used) 1039339640Smm{ 1040339640Smm printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n", 1041339640Smm (used) ? " " : "* ", 1042339640Smm auxi, 1043348608Smm (long) u.isym, 1044339640Smm (long) u.rndx.rfd, 1045348608Smm (long) u.rndx.index, 1046348608Smm u.ti.bt, 1047339640Smm u.ti.fBitfield, 1048348608Smm u.ti.continued, 1049348608Smm u.ti.tq0, 1050348608Smm u.ti.tq1, 1051348608Smm u.ti.tq2, 1052348608Smm u.ti.tq3, 1053339640Smm u.ti.tq4, 1054348608Smm u.ti.tq5); 1055348608Smm} 1056348608Smm 1057339640Smm 1058348608Smm/* Write aggregate information to a string. */ 1059348608Smm 1060339640Smmstatic void 1061348608Smmemit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp) 1062339640Smm{ 1063348608Smm unsigned int ifd = u.rndx.rfd; 1064348608Smm unsigned int index = u.rndx.index; 1065339640Smm const char *name; 1066348608Smm 1067339640Smm if (ifd == ST_RFDESCAPE) 1068339640Smm ifd = u2.isym; 1069339640Smm 1070348608Smm /* An ifd of -1 is an opaque type. An escaped index of 0 is a 1071348608Smm struct return type of a procedure compiled without -g. */ 1072348608Smm if (ifd == 0xffffffff 1073339640Smm || (u.rndx.rfd == ST_RFDESCAPE && index == 0)) 1074348608Smm name = "<undefined>"; 1075348608Smm else if (index == indexNil) 1076339640Smm name = "<no name>"; 1077339640Smm else 1078339640Smm { 1079348608Smm if (fdp == 0 || sym_hdr.crfd == 0) 1080348608Smm fdp = &file_desc[ifd]; 1081348608Smm else 1082339640Smm fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]]; 1083348608Smm name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss]; 1084348608Smm } 1085339640Smm 1086339640Smm sprintf (string, 1087339640Smm "%s %s { ifd = %u, index = %u }", 1088348608Smm which, name, ifd, index); 1089358090Smm} 1090339640Smm 1091358090Smm 1092358090Smm/* Print out information about a file descriptor, and the symbols, 1093358090Smm procedures, and line numbers within it. */ 1094348608Smm 1095339640Smmstatic void 1096358090Smmprint_file_desc (FDR *fdp, int number) 1097348608Smm{ 1098339640Smm char *str_base; 1099348608Smm AUXU *aux_base; 1100339640Smm int symi, pdi; 1101339640Smm int width = 20; 1102339640Smm char *used_base; 1103348608Smm 1104339640Smm str_base = l_strings + fdp->issBase; 1105348608Smm aux_base = aux_symbols + fdp->iauxBase; 1106348608Smm used_base = aux_used + (aux_base - aux_symbols); 1107339640Smm 1108348608Smm printf ("\nFile #%d, \"%s\"\n\n", 1109348608Smm number, 1110348608Smm fdp->rss != issNil ? str_base + fdp->rss : "<unknown>"); 1111348608Smm 1112339640Smm printf (" Name index = %-10ld Readin = %s\n", 1113348608Smm (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No"); 1114339640Smm 1115339640Smm printf (" Merge = %-10s Endian = %s\n", 1116348608Smm (fdp->fMerge) ? "Yes" : "No", 1117348608Smm (fdp->fBigendian) ? "BIG" : "LITTLE"); 1118348608Smm 1119348608Smm printf (" Debug level = %-10s Language = %s\n", 1120348608Smm glevel_to_string (fdp->glevel), 1121339640Smm lang_to_string((lang_t) fdp->lang)); 1122348608Smm 1123348608Smm printf (" Adr = 0x%08lx\n\n", (long) fdp->adr); 1124348608Smm 1125339640Smm printf(" %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset"); 1126348608Smm printf(" %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======"); 1127339640Smm 1128339640Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1129339640Smm width, "Local strings", 1130348608Smm (ulong) fdp->issBase, 1131348608Smm (ulong) fdp->cbSs, 1132339640Smm (ulong) fdp->cbSs, 1133339640Smm (ulong) (fdp->issBase + sym_hdr.cbSsOffset)); 1134349525Smm 1135349525Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1136349525Smm width, "Local symbols", 1137349525Smm (ulong) fdp->isymBase, 1138349525Smm (ulong) fdp->csym, 1139349525Smm (ulong) (fdp->csym * sizeof (SYMR)), 1140349525Smm (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset)); 1141339640Smm 1142348608Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1143348608Smm width, "Line numbers", 1144348608Smm (ulong) fdp->cbLineOffset, 1145348608Smm (ulong) fdp->cline, 1146348608Smm (ulong) fdp->cbLine, 1147348608Smm (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset)); 1148348608Smm 1149339640Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1150339640Smm width, "Optimization symbols", 1151339640Smm (ulong) fdp->ioptBase, 1152348608Smm (ulong) fdp->copt, 1153339640Smm (ulong) (fdp->copt * sizeof (OPTR)), 1154348608Smm (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset)); 1155339640Smm 1156358090Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1157358090Smm width, "Procedures", 1158358090Smm (ulong) fdp->ipdFirst, 1159358090Smm (ulong) fdp->cpd, 1160348608Smm (ulong) (fdp->cpd * sizeof (PDR)), 1161348608Smm (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset)); 1162348608Smm 1163339640Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1164348608Smm width, "Auxiliary symbols", 1165348608Smm (ulong) fdp->iauxBase, 1166348608Smm (ulong) fdp->caux, 1167348608Smm (ulong) (fdp->caux * sizeof (AUXU)), 1168339640Smm (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset)); 1169348608Smm 1170348608Smm printf(" %-*s %11lu %11lu %11lu %11lu\n", 1171339640Smm width, "Relative Files", 1172348608Smm (ulong) fdp->rfdBase, 1173348608Smm (ulong) fdp->crfd, 1174348608Smm (ulong) (fdp->crfd * sizeof (ulong)), 1175348608Smm (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset)); 1176339640Smm 1177348608Smm 1178348608Smm if (want_scope && cur_scope != (scope_t *) 0) 1179339640Smm printf ("\n Warning scope does not start at 0!\n"); 1180348608Smm 1181339640Smm /* 1182339640Smm * print the info about the symbol table. 1183339640Smm */ 1184348608Smm printf ("\n There are %lu local symbols, starting at %lu\n", 1185339640Smm (ulong) fdp->csym, 1186358090Smm (ulong) (fdp->isymBase + sym_hdr.cbSymOffset)); 1187348608Smm 1188339640Smm for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++) 1189358090Smm print_symbol (&l_symbols[symi], 1190358090Smm symi - fdp->isymBase, 1191358090Smm str_base, 1192358090Smm aux_base, 1193348608Smm -1, 1194348608Smm fdp); 1195339640Smm 1196348608Smm if (want_scope && cur_scope != (scope_t *) 0) 1197348608Smm printf ("\n Warning scope does not end at 0!\n"); 1198348608Smm 1199348608Smm /* 1200339640Smm * print the aux. table if desired. 1201348608Smm */ 1202348608Smm 1203348608Smm if (want_aux && fdp->caux != 0) 1204348608Smm { 1205348608Smm int auxi; 1206339640Smm 1207348608Smm printf ("\n There are %lu auxiliary table entries, starting at %lu.\n\n", 1208348608Smm (ulong) fdp->caux, 1209339640Smm (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset)); 1210348608Smm 1211348608Smm for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++) 1212339640Smm print_aux (aux_base[auxi], auxi, used_base[auxi]); 1213348608Smm } 1214348608Smm 1215348608Smm /* 1216339640Smm * print the relative file descriptors. 1217348608Smm */ 1218348608Smm if (want_rfd && fdp->crfd != 0) 1219348608Smm { 1220348608Smm ulong *rfd_ptr, i; 1221348608Smm 1222348608Smm printf ("\n There are %lu relative file descriptors, starting at %lu.\n", 1223339640Smm (ulong) fdp->crfd, 1224348608Smm (ulong) fdp->rfdBase); 1225339640Smm 1226339640Smm rfd_ptr = rfile_desc + fdp->rfdBase; 1227339640Smm for (i = 0; i < (ulong) fdp->crfd; i++) 1228348608Smm { 1229348608Smm printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr); 1230348608Smm rfd_ptr++; 1231339640Smm } 1232339640Smm } 1233339640Smm 1234348608Smm /* 1235339640Smm * do the procedure descriptors. 1236348608Smm */ 1237348608Smm printf ("\n There are %lu procedure descriptor entries, ", (ulong) fdp->cpd); 1238348608Smm printf ("starting at %lu.\n", (ulong) fdp->ipdFirst); 1239348608Smm 1240339640Smm for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++) 1241348608Smm { 1242348608Smm PDR *proc_ptr = &proc_desc[pdi]; 1243348608Smm printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst)); 1244348608Smm 1245348608Smm if (l_symbols != 0) 1246348608Smm printf ("\t Name index = %-11ld Name = \"%s\"\n", 1247339640Smm (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss, 1248348608Smm l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base); 1249348608Smm 1250348608Smm printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n", 1251339640Smm (long) proc_ptr->regmask, 1252348608Smm (long) proc_ptr->regoffset, 1253339640Smm (long) proc_ptr->fregmask, 1254339640Smm (long) proc_ptr->fregoffset); 1255348608Smm 1256348608Smm printf ("\t .frame $%d,%ld,$%d\n", 1257348608Smm (int) proc_ptr->framereg, 1258348608Smm (long) proc_ptr->frameoffset, 1259348608Smm (int) proc_ptr->pcreg); 1260348608Smm 1261348608Smm printf ("\t Opt. start = %-11ld Symbols start = %ld\n", 1262348608Smm (long) proc_ptr->iopt, 1263358090Smm (long) proc_ptr->isym); 1264348608Smm 1265348608Smm printf ("\t First line # = %-11ld Last line # = %ld\n", 1266348608Smm (long) proc_ptr->lnLow, 1267348608Smm (long) proc_ptr->lnHigh); 1268348608Smm 1269348608Smm printf ("\t Line Offset = %-11ld Address = 0x%08lx\n", 1270348608Smm (long) proc_ptr->cbLineOffset, 1271348608Smm (long) proc_ptr->adr); 1272348608Smm 1273348608Smm /* 1274348608Smm * print the line number entries. 1275348608Smm */ 1276348608Smm 1277348608Smm if (want_line && fdp->cline != 0) 1278348608Smm { 1279348608Smm int delta, count; 1280348608Smm long cur_line = proc_ptr->lnLow; 1281348608Smm uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset 1282358090Smm + fdp->cbLineOffset); 1283348608Smm uchar *line_end; 1284348608Smm 1285348608Smm if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */ 1286348608Smm line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset; 1287348608Smm else /* not last proc. */ 1288348608Smm line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset 1289348608Smm + fdp->cbLineOffset); 1290348608Smm 1291348608Smm printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n", 1292348608Smm (ulong) (line_end - line_ptr), 1293348608Smm (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset)); 1294348608Smm 1295348608Smm while (line_ptr < line_end) 1296348608Smm { /* sign extend nibble */ 1297348608Smm delta = ((*line_ptr >> 4) ^ 0x8) - 0x8; 1298348608Smm count = (*line_ptr & 0xf) + 1; 1299348608Smm if (delta != -8) 1300348608Smm line_ptr++; 1301348608Smm else 1302348608Smm { 1303348608Smm delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff); 1304348608Smm delta = (delta ^ 0x8000) - 0x8000; 1305348608Smm line_ptr += 3; 1306348608Smm } 1307348608Smm 1308348608Smm cur_line += delta; 1309339640Smm printf ("\t Line %11ld, delta %5d, count %2d\n", 1310348608Smm cur_line, 1311339640Smm delta, 1312348608Smm count); 1313358090Smm } 1314348608Smm } 1315339640Smm } 1316348608Smm} 1317348608Smm 1318348608Smm 1319348608Smm/* Read in the portions of the .T file that we will print out. */ 1320348608Smm 1321348608Smmstatic void 1322348608Smmread_tfile (void) 1323339640Smm{ 1324348608Smm short magic; 1325348608Smm off_t sym_hdr_offset = 0; 1326339640Smm 1327348608Smm read_seek (&magic, sizeof (magic), 0, "Magic number"); 1328348608Smm if (!tfile) 1329348608Smm { 1330348608Smm /* Print out the global header, since this is not a T-file. */ 1331339640Smm 1332348608Smm read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header"); 1333339640Smm 1334348608Smm print_global_hdr (&global_hdr); 1335348608Smm 1336348608Smm if (global_hdr.f_symptr == 0) 1337348608Smm { 1338348608Smm printf ("No symbolic header, Goodbye!\n"); 1339339640Smm exit (1); 1340348608Smm } 1341348608Smm 1342348608Smm sym_hdr_offset = global_hdr.f_symptr; 1343348608Smm } 1344348608Smm 1345339640Smm read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header"); 1346348608Smm 1347348608Smm print_sym_hdr (&sym_hdr); 1348348608Smm 1349348608Smm lines = read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset, 1350348608Smm "Line numbers"); 1351339640Smm 1352348608Smm dense_nums = read_seek (NULL, sym_hdr.idnMax * sizeof (DNR), 1353348608Smm sym_hdr.cbDnOffset, "Dense numbers"); 1354348608Smm 1355339640Smm proc_desc = read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR), 1356348608Smm sym_hdr.cbPdOffset, "Procedure tables"); 1357348608Smm 1358339640Smm l_symbols = read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR), 1359348608Smm sym_hdr.cbSymOffset, "Local symbols"); 1360339640Smm 1361339640Smm opt_symbols = read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR), 1362348608Smm sym_hdr.cbOptOffset, "Optimization symbols"); 1363348608Smm 1364339640Smm aux_symbols = read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU), 1365348608Smm sym_hdr.cbAuxOffset, "Auxiliary symbols"); 1366348608Smm 1367348608Smm if (sym_hdr.iauxMax > 0) 1368348608Smm aux_used = xcalloc (sym_hdr.iauxMax, 1); 1369339640Smm 1370348608Smm l_strings = read_seek (NULL, sym_hdr.issMax, 1371348608Smm sym_hdr.cbSsOffset, "Local string table"); 1372348608Smm 1373348608Smm e_strings = read_seek (NULL, sym_hdr.issExtMax, 1374348608Smm sym_hdr.cbSsExtOffset, "External string table"); 1375339640Smm 1376348608Smm file_desc = read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR), 1377348608Smm sym_hdr.cbFdOffset, "File tables"); 1378348608Smm 1379348608Smm rfile_desc = read_seek (NULL, sym_hdr.crfd * sizeof (ulong), 1380348608Smm sym_hdr.cbRfdOffset, "Relative file tables"); 1381339640Smm 1382348608Smm e_symbols = read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR), 1383348608Smm sym_hdr.cbExtOffset, "External symbols"); 1384348608Smm} 1385339640Smm 1386348608Smm 1387348608Smm 1388339640Smmextern int main (int, char **); 1389348608Smm 1390348608Smmint 1391348608Smmmain (int argc, char **argv) 1392348608Smm{ 1393348608Smm int i, opt; 1394339640Smm 1395348608Smm /* 1396348608Smm * Process arguments 1397348608Smm */ 1398348608Smm while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1) 1399348608Smm switch (opt) 1400339640Smm { 1401348608Smm default: errors++; break; 1402348608Smm case 'a': want_aux++; break; /* print aux table */ 1403339640Smm case 'l': want_line++; break; /* print line numbers */ 1404348608Smm case 'r': want_rfd++; break; /* print relative fd's */ 1405348608Smm case 's': want_scope++; break; /* print scope info */ 1406348608Smm case 'v': verbose++; break; /* print version # */ 1407348608Smm case 'V': version++; break; /* print version # */ 1408348608Smm case 't': tfile++; break; /* this is a tfile (without header), 1409348608Smm and not a .o */ 1410348608Smm } 1411348608Smm 1412348608Smm if (version) 1413348608Smm { 1414348608Smm printf ("mips-tdump (GCC) %s\n", version_string); 1415348608Smm fputs ("Copyright (C) 2006 Free Software Foundation, Inc.\n", stdout); 1416348608Smm fputs ("This is free software; see the source for copying conditions. There is NO\n\ 1417348608Smmwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n", 1418348608Smm stdout); 1419348608Smm exit (0); 1420348608Smm } 1421348608Smm 1422348608Smm if (optind != argc - 1) 1423348608Smm errors++; 1424348608Smm 1425348608Smm if (verbose || errors) 1426348608Smm { 1427348608Smm fprintf (stderr, "mips-tdump (GCC) %s", version_string); 1428348608Smm#ifdef TARGET_VERSION 1429348608Smm TARGET_VERSION; 1430348608Smm#endif 1431339640Smm fputc ('\n', stderr); 1432339640Smm } 1433348608Smm 1434348608Smm if (errors) 1435348608Smm { 1436348608Smm fprintf (stderr, "Calling Sequence:\n"); 1437348608Smm fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]); 1438348608Smm fprintf (stderr, "\n"); 1439348608Smm fprintf (stderr, "switches:\n"); 1440348608Smm fprintf (stderr, "\t-a Print out auxiliary table.\n"); 1441348608Smm fprintf (stderr, "\t-l Print out line numbers.\n"); 1442348608Smm fprintf (stderr, "\t-r Print out relative file descriptors.\n"); 1443348608Smm fprintf (stderr, "\t-s Print out the current scopes for an item.\n"); 1444348608Smm fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n"); 1445348608Smm fprintf (stderr, "\t-v Print program version.\n"); 1446348608Smm return 1; 1447348608Smm } 1448348608Smm 1449348608Smm /* 1450348608Smm * Open and process the input file. 1451348608Smm */ 1452348608Smm tfile_fd = open (argv[optind], O_RDONLY); 1453348608Smm if (tfile_fd < 0) 1454348608Smm { 1455348608Smm perror (argv[optind]); 1456348608Smm return 1; 1457348608Smm } 1458348608Smm 1459348608Smm read_tfile (); 1460348608Smm 1461348608Smm /* 1462348608Smm * Print any global aux words if any. 1463348608Smm */ 1464348608Smm if (want_aux) 1465348608Smm { 1466348608Smm long last_aux_in_use; 1467348608Smm 1468348608Smm if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0) 1469348608Smm { 1470348608Smm printf ("\nGlobal auxiliary entries before first file:\n"); 1471348608Smm for (i = 0; i < file_desc[0].iauxBase; i++) 1472348608Smm print_aux (aux_symbols[i], 0, aux_used[i]); 1473348608Smm } 1474348608Smm 1475348608Smm if (sym_hdr.ifdMax == 0) 1476348608Smm last_aux_in_use = 0; 1477348608Smm else 1478348608Smm last_aux_in_use 1479348608Smm = (file_desc[sym_hdr.ifdMax-1].iauxBase 1480348608Smm + file_desc[sym_hdr.ifdMax-1].caux - 1); 1481348608Smm 1482348608Smm if (last_aux_in_use < sym_hdr.iauxMax-1) 1483348608Smm { 1484348608Smm printf ("\nGlobal auxiliary entries after last file:\n"); 1485348608Smm for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++) 1486348608Smm print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]); 1487348608Smm } 1488348608Smm } 1489348608Smm 1490348608Smm /* 1491348608Smm * Print the information for each file. 1492348608Smm */ 1493348608Smm for (i = 0; i < sym_hdr.ifdMax; i++) 1494348608Smm print_file_desc (&file_desc[i], i); 1495348608Smm 1496348608Smm /* 1497348608Smm * Print the external symbols. 1498348608Smm */ 1499348608Smm want_scope = 0; /* scope info is meaning for extern symbols */ 1500348608Smm printf ("\nThere are %lu external symbols, starting at %lu\n", 1501348608Smm (ulong) sym_hdr.iextMax, 1502348608Smm (ulong) sym_hdr.cbExtOffset); 1503348608Smm 1504348608Smm for(i = 0; i < sym_hdr.iextMax; i++) 1505348608Smm print_symbol (&e_symbols[i].asym, i, e_strings, 1506348608Smm aux_symbols + file_desc[e_symbols[i].ifd].iauxBase, 1507348608Smm e_symbols[i].ifd, 1508348608Smm &file_desc[e_symbols[i].ifd]); 1509348608Smm 1510348608Smm /* 1511348608Smm * Print unused aux symbols now. 1512348608Smm */ 1513348608Smm 1514348608Smm if (want_aux) 1515348608Smm { 1516348608Smm int first_time = 1; 1517348608Smm 1518348608Smm for (i = 0; i < sym_hdr.iauxMax; i++) 1519348608Smm { 1520348608Smm if (! aux_used[i]) 1521348608Smm { 1522348608Smm if (first_time) 1523348608Smm { 1524348608Smm printf ("\nThe following auxiliary table entries were unused:\n\n"); 1525348608Smm first_time = 0; 1526348608Smm } 1527348608Smm 1528348608Smm printf (" #%-5d %11ld 0x%08lx %s\n", 1529348608Smm i, 1530348608Smm (long) aux_symbols[i].isym, 1531348608Smm (long) aux_symbols[i].isym, 1532348608Smm type_to_string (aux_symbols, i, (FDR *) 0)); 1533348608Smm } 1534348608Smm } 1535348608Smm } 1536348608Smm 1537348608Smm return 0; 1538348608Smm} 1539348608Smm