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