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