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