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