re PR target/13926 (GCC generates jumps that are too large to fit in word displacemen...
[gcc.git] / gcc / mips-tdump.c
1 /* Read and manage MIPS symbol tables from object modules.
2 Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003
3 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 2, 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 COPYING. If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, 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_COMPILE
33 #include <a.out.h>
34 #else
35 #include "mips/a.out.h"
36 #endif /* CROSS_COMPILE */
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 \f
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
72 typedef 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
101 typedef 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 (ie. 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
133 typedef 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
145 typedef 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
178 typedef 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
192 typedef 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 \f
200 /* Keep track of the active scopes. */
201 typedef 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
208 struct filehdr global_hdr; /* a.out header */
209
210 int errors = 0; /* # of errors */
211 int want_aux = 0; /* print aux table */
212 int want_line = 0; /* print line numbers */
213 int want_rfd = 0; /* print relative file desc's */
214 int want_scope = 0; /* print scopes for every symbol */
215 int tfile = 0; /* no global header file */
216 int version = 0; /* print version # */
217 int verbose = 0;
218 int tfile_fd; /* file descriptor of .T file */
219 off_t tfile_offset; /* current offset in .T file */
220 scope_t *cur_scope = 0; /* list of active scopes */
221 scope_t *free_scope = 0; /* list of freed scopes */
222 HDRR sym_hdr; /* symbolic header */
223 char *l_strings; /* local strings */
224 char *e_strings; /* external strings */
225 SYMR *l_symbols; /* local symbols */
226 EXTR *e_symbols; /* external symbols */
227 LINER *lines; /* line numbers */
228 DNR *dense_nums; /* dense numbers */
229 OPTR *opt_symbols; /* optimization symbols */
230 AUXU *aux_symbols; /* Auxiliary symbols */
231 char *aux_used; /* map of which aux syms are used */
232 FDR *file_desc; /* file tables */
233 ulong *rfile_desc; /* relative file tables */
234 PDR *proc_desc; /* procedure tables */
235
236 /* Forward reference for functions. */
237 static void *read_seek (void *, size_t, off_t, const char *);
238 static void read_tfile (void);
239 static void print_global_hdr (struct filehdr *);
240 static void print_sym_hdr (HDRR *);
241 static void print_file_desc (FDR *, int);
242 static void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
243 static void print_aux (AUXU, int, int);
244 static void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
245 static const char *st_to_string (st_t);
246 static const char *sc_to_string (sc_t);
247 static const char *glevel_to_string (glevel_t);
248 static const char *lang_to_string (lang_t);
249 static const char *type_to_string (AUXU *, int, FDR *);
250
251 extern char *optarg;
252 extern int optind;
253 extern 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},
258 const 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
265 static const struct option options[] =
266 {
267 { "version", 0, 0, 'V' },
268 { "verbose", 0, 0, 'v' },
269 { 0, 0, 0, 0 }
270 };
271 \f
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
277 static void *
278 read_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 \f
307 /* Convert language code to string format. */
308
309 static const char *
310 lang_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 \f
329 /* Convert storage class to string. */
330
331 static const char *
332 sc_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 \f
366 /* Convert symbol type to string. */
367
368 static const char *
369 st_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 \f
406 /* Convert debug level to string. */
407
408 static const char *
409 glevel_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 \f
423 /* Convert the type information to string format. */
424
425 static const char *
426 type_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 (ie, 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 (ie, 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 \f
733 /* Print out the global file header for object files. */
734
735 static void
736 print_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 \f
787 /* Print out the symbolic header. */
788
789 static void
790 print_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 \f
860 /* Print out a symbol. */
861
862 static void
863 print_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 \f
1035 /* Print out a word from the aux. table in various formats. */
1036
1037 static void
1038 print_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 \f
1058 /* Write aggregate information to a string. */
1059
1060 static void
1061 emit_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 \f
1092 /* Print out information about a file descriptor, and the symbols,
1093 procedures, and line numbers within it. */
1094
1095 static void
1096 print_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 \f
1319 /* Read in the portions of the .T file that we will print out. */
1320
1321 static void
1322 read_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 \f
1387
1388 extern int main (int, char **);
1389
1390 int
1391 main (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) 2003 Free Software Foundation, Inc.\n", stdout);
1416 fputs ("This is free software; see the source for copying conditions. There is NO\n\
1417 warranty; 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 }