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