1 /* Update the symbol table (the .T file) in a MIPS object to
2 contain debugging information specified by the GNU compiler
3 in the form of comments (the mips assembler does not support
4 assembly access to debug information).
5 Contributed by: Michael Meissner, meissner@osf.org
6 Copyright (C) 1991 Free Software Foundation, Inc.
8 This file is part of GNU CC.
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 /* Here is a brief description of the MIPS ECOFF symbol table. The
26 MIPS symbol table has the following pieces:
32 +-- Dense number table
40 +-- Relative file descriptors
52 The symbolic header points to each of the other tables, and also
53 contains the number of entries. It also contains a magic number
54 and MIPS compiler version number, such as 2.0.
56 The auxiliary table is a series of 32 bit integers, that are
57 referenced as needed from the local symbol table. Unlike standard
58 COFF, the aux. information does not follow the symbol that uses
59 it, but rather is a separate table. In theory, this would allow
60 the MIPS compilers to collapse duplicate aux. entries, but I've not
61 noticed this happening with the 1.31 compiler suite. The different
62 types of aux. entries are:
64 1) dnLow: Low bound on array dimension.
66 2) dnHigh: High bound on array dimension.
68 3) isym: Index to the local symbol which is the start of the
69 function for the end of function first aux. entry.
71 4) width: Width of structures and bitfields.
73 5) count: Count of ranges for variant part.
75 6) rndx: A relative index into the symbol table. The relative
76 index field has two parts: rfd which is a pointer into the
77 relative file index table or ST_RFDESCAPE which says the next
78 aux. entry is the file number, and index: which is the pointer
79 into the local symbol within a given file table. This is for
80 things like references to types defined in another file.
82 7) Type information: This is like the COFF type bits, except it
83 is 32 bits instead of 16; they still have room to add new
84 basic types; and they can handle more than 6 levels of array,
85 pointer, function, etc. Each type information field contains
86 the following structure members:
88 a) fBitfield: a bit that says this is a bitfield, and the
89 size in bits follows as the next aux. entry.
91 b) continued: a bit that says the next aux. entry is a
92 continuation of the current type information (in case
93 there are more than 6 levels of array/ptr/function).
95 c) bt: an integer containing the base type before adding
96 array, pointer, function, etc. qualifiers. The
97 current base types that I have documentation for are:
100 btAdr -- address - integer same size as ptr
102 btUChar -- unsigned character
104 btUShort -- unsigned short
106 btUInt -- unsigned int
108 btULong -- unsigned long
109 btFloat -- float (real)
110 btDouble -- Double (real)
111 btStruct -- Structure (Record)
112 btUnion -- Union (variant)
114 btTypedef -- defined via a typedef isymRef
115 btRange -- subrange of int
117 btComplex -- fortran complex
118 btDComplex -- fortran double complex
119 btIndirect -- forward or unnamed typedef
120 btFixedDec -- Fixed Decimal
121 btFloatDec -- Float Decimal
122 btString -- Varying Length Character String
123 btBit -- Aligned Bit String
125 btVoid -- Void (MIPS cc revision >= 2.00)
127 d) tq0 - tq5: type qualifier fields as needed. The
128 current type qualifier fields I have documentation for
131 tqNil -- no more qualifiers
135 tqFar -- 8086 far pointers
139 The dense number table is used in the front ends, and disappears by
140 the time the .o is created.
142 With the 1.31 compiler suite, the optimization symbols don't seem
143 to be used as far as I can tell.
145 The linker is the first entity that creates the relative file
146 descriptor table, and I believe it is used so that the individual
147 file table pointers don't have to be rewritten when the objects are
148 merged together into the program file.
150 Unlike COFF, the basic symbol & string tables are split into
151 external and local symbols/strings. The relocation information
152 only goes off of the external symbol table, and the debug
153 information only goes off of the internal symbol table. The
154 external symbols can have links to an appropriate file index and
155 symbol within the file to give it the appropriate type information.
156 Because of this, the external symbols are actually larger than the
157 internal symbols (to contain the link information), and contain the
158 local symbol structure as a member, though this member is not the
159 first member of the external symbol structure (!). I suspect this
160 split is to make strip easier to deal with.
162 Each file table has offsets for where the line numbers, local
163 strings, local symbols, and procedure table starts from within the
164 global tables, and the indexs are reset to 0 for each of those
167 The procedure table contains the binary equivalents of the .ent
168 (start of the function address), .frame (what register is the
169 virtual frame pointer, constant offset from the register to obtain
170 the VFP, and what register holds the return address), .mask/.fmask
171 (bitmask of saved registers, and where the first register is stored
172 relative to the VFP) assembler directives. It also contains the
173 low and high bounds of the line numbers if debugging is turned on.
175 The line number table is a compressed form of the normal COFF line
176 table. Each line number entry is either 1 or 3 bytes long, and
177 contains a signed delta from the previous line, and an unsigned
178 count of the number of instructions this statement takes.
180 The local symbol table contains the following fields:
182 1) iss: index to the local string table giving the name of the
185 2) value: value of the symbol (address, register number, etc.).
187 3) st: symbol type. The current symbol types are:
189 stNil -- Nuthin' special
190 stGlobal -- external symbol
192 stParam -- procedure argument
193 stLocal -- local variable
195 stProc -- External Procedure
196 stBlock -- beginnning of block
197 stEnd -- end (of anything)
198 stMember -- member (of anything)
199 stTypedef -- type definition
201 stRegReloc -- register relocation
202 stForward -- forwarding address
203 stStaticProc -- Static procedure
206 4) sc: storage class. The current storage classes are:
208 scText -- text symbol
209 scData -- initialized data symbol
210 scBss -- un-initialized data symbol
211 scRegister -- value of symbol is register number
212 scAbs -- value of symbol is absolute
213 scUndefined -- who knows?
214 scCdbLocal -- variable's value is IN se->va.??
215 scBits -- this is a bit field
216 scCdbSystem -- value is IN debugger's address space
217 scRegImage -- register value saved on stack
218 scInfo -- symbol contains debugger information
219 scUserStruct -- addr in struct user for current process
220 scSData -- load time only small data
221 scSBss -- load time only small common
222 scRData -- load time only read only data
223 scVar -- Var parameter (fortranpascal)
224 scCommon -- common variable
225 scSCommon -- small common
226 scVarRegister -- Var parameter in a register
227 scVariant -- Variant record
228 scSUndefined -- small undefined(external) data
229 scInit -- .init section symbol
231 5) index: pointer to a local symbol or aux. entry.
235 For the following program:
240 printf("Hello World!\n");
244 Mips-tdump produces the following information:
249 timestamp 645311799, Wed Jun 13 17:16:39 1990
250 symbolic header offset 284
251 symbolic header size 96
255 Symbolic header, magic number = 0x7009, vstamp = 1.31:
257 Info Offset Number Bytes
258 ==== ====== ====== =====
260 Line numbers 380 4 4 [13]
262 Procedures Tables 384 1 52
263 Local Symbols 436 16 192
264 Optimization Symbols 0 0 0
265 Auxilary Symbols 628 39 156
266 Local Strings 784 80 80
267 External Strings 864 144 144
268 File Tables 1008 2 144
270 External Symbols 1152 20 320
274 Name index = 1 Readin = No
275 Merge = No Endian = LITTLE
276 Debug level = G2 Language = C
279 Info Start Number Size Offset
280 ==== ===== ====== ==== ======
281 Local strings 0 15 15 784
282 Local symbols 0 6 72 436
283 Line numbers 0 13 13 380
284 Optimization symbols 0 0 0 0
285 Procedures 0 1 52 384
286 Auxiliary symbols 0 14 56 628
287 Relative Files 0 0 0 0
289 There are 6 local symbols, starting at 436
291 Symbol# 0: "hello2.c"
294 Storage class = Text Index = 6
295 Symbol type = File Value = 0
301 Storage class = Text Index = 12
302 Symbol type = Proc Value = 0
307 Storage class = Text Index = 4
308 Symbol type = Block Value = 8
313 Storage class = Text Index = 2
314 Symbol type = End Value = 28
319 Storage class = Text Index = 1
320 Symbol type = End Value = 52
322 Symbol# 5: "hello2.c"
325 Storage class = Text Index = 0
326 Symbol type = End Value = 0
328 There are 14 auxiliary table entries, starting at 628.
330 * #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
331 * #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
332 * #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0]
333 * #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0]
334 * #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
335 * #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0]
336 * #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0]
337 * #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0]
338 * #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0]
339 * #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0]
340 * #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0]
341 * #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0]
342 #12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0]
343 #13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
345 There are 1 procedure descriptor entries, starting at 0.
347 Procedure descriptor 0:
348 Name index = 10 Name = "main"
349 .mask 0x80000000,-4 .fmask 0x00000000,0
351 Opt. start = -1 Symbols start = 1
352 First line # = 3 Last line # = 6
353 Line Offset = 0 Address = 0x00000000
355 There are 4 bytes holding line numbers, starting at 380.
356 Line 3, delta 0, count 2
357 Line 4, delta 1, count 3
358 Line 5, delta 1, count 2
359 Line 6, delta 1, count 6
361 File #1, "/usr/include/stdio.h"
363 Name index = 1 Readin = No
364 Merge = Yes Endian = LITTLE
365 Debug level = G2 Language = C
368 Info Start Number Size Offset
369 ==== ===== ====== ==== ======
370 Local strings 15 65 65 799
371 Local symbols 6 10 120 508
372 Line numbers 0 0 0 380
373 Optimization symbols 0 0 0 0
375 Auxiliary symbols 14 25 100 684
376 Relative Files 0 0 0 0
378 There are 10 local symbols, starting at 442
380 Symbol# 0: "/usr/include/stdio.h"
383 Storage class = Text Index = 10
384 Symbol type = File Value = 0
389 Storage class = Info Index = 9
390 Symbol type = Block Value = 20
395 Storage class = Info Index = 4
396 Symbol type = Member Value = 0
401 Storage class = Info Index = 15
402 Symbol type = Member Value = 32
407 Storage class = Info Index = 16
408 Symbol type = Member Value = 64
413 Storage class = Info Index = 4
414 Symbol type = Member Value = 96
419 Storage class = Info Index = 3
420 Symbol type = Member Value = 128
425 Storage class = Info Index = 2
426 Symbol type = Member Value = 144
431 Storage class = Info Index = 1
432 Symbol type = End Value = 0
434 Symbol# 9: "/usr/include/stdio.h"
437 Storage class = Text Index = 0
438 Symbol type = End Value = 0
440 There are 25 auxiliary table entries, starting at 642.
442 * #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
443 #15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
444 #16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
445 * #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0]
446 * #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1]
447 * #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
448 * #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4]
449 * #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
450 * #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
451 * #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0]
452 * #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0]
453 * #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
454 * #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
455 * #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
456 * #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
457 * #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
458 * #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
459 * #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
460 * #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
461 * #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
462 * #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
463 * #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
464 * #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
465 * #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
466 * #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
468 There are 0 procedure descriptor entries, starting at 1.
470 There are 20 external symbols, starting at 1152
473 Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
474 String index = 0 Ifd = 1
475 Storage class = Nil Index = 17
476 Symbol type = Global Value = 60
479 String index = 5 Ifd = 1
480 Storage class = Nil Index = 1048575
481 Symbol type = Proc Value = 0
484 String index = 11 Ifd = 1
485 Storage class = Nil Index = 1048575
486 Symbol type = Proc Value = 0
489 String index = 18 Ifd = 1
490 Storage class = Nil Index = 1048575
491 Symbol type = Proc Value = 0
494 String index = 26 Ifd = 1
495 Storage class = Nil Index = 1048575
496 Symbol type = Proc Value = 0
499 String index = 32 Ifd = 1
500 Storage class = Nil Index = 1048575
501 Symbol type = Proc Value = 0
504 String index = 40 Ifd = 1
505 Storage class = Nil Index = 1048575
506 Symbol type = Proc Value = 0
509 String index = 46 Ifd = 1
510 Storage class = Nil Index = 1048575
511 Symbol type = Proc Value = 0
514 String index = 53 Ifd = 1
515 Storage class = Nil Index = 1048575
516 Symbol type = Proc Value = 0
518 Symbol# 9: "setbuffer"
519 String index = 60 Ifd = 1
520 Storage class = Nil Index = 1048575
521 Symbol type = Proc Value = 0
523 Symbol# 10: "setlinebuf"
524 String index = 70 Ifd = 1
525 Storage class = Nil Index = 1048575
526 Symbol type = Proc Value = 0
529 String index = 81 Ifd = 1
530 Storage class = Nil Index = 1048575
531 Symbol type = Proc Value = 0
534 String index = 87 Ifd = 1
535 Storage class = Nil Index = 1048575
536 Symbol type = Proc Value = 0
538 Symbol# 13: "ctermid"
539 String index = 92 Ifd = 1
540 Storage class = Nil Index = 1048575
541 Symbol type = Proc Value = 0
543 Symbol# 14: "cuserid"
544 String index = 100 Ifd = 1
545 Storage class = Nil Index = 1048575
546 Symbol type = Proc Value = 0
548 Symbol# 15: "tempnam"
549 String index = 108 Ifd = 1
550 Storage class = Nil Index = 1048575
551 Symbol type = Proc Value = 0
554 String index = 116 Ifd = 1
555 Storage class = Nil Index = 1048575
556 Symbol type = Proc Value = 0
558 Symbol# 17: "sprintf"
559 String index = 123 Ifd = 1
560 Storage class = Nil Index = 1048575
561 Symbol type = Proc Value = 0
565 String index = 131 Ifd = 0
566 Storage class = Text Index = 1
567 Symbol type = Proc Value = 0
570 String index = 136 Ifd = 0
571 Storage class = Undefined Index = 1048575
572 Symbol type = Proc Value = 0
574 The following auxiliary table entries were unused:
578 #3 16 0x00000010 short
580 #5 32 0x00000020 long
581 #6 40 0x00000028 float
582 #7 44 0x0000002c double
583 #8 12 0x0000000c unsigned char
584 #9 20 0x00000014 unsigned short
585 #10 28 0x0000001c unsigned int
586 #11 36 0x00000024 unsigned long
587 #14 0 0x00000000 void
588 #15 24 0x00000018 int
589 #19 32 0x00000020 long
590 #20 40 0x00000028 float
591 #21 44 0x0000002c double
592 #22 12 0x0000000c unsigned char
593 #23 20 0x00000014 unsigned short
594 #24 28 0x0000001c unsigned int
595 #25 36 0x00000024 unsigned long
596 #26 48 0x00000030 struct no name { ifd = -1, index = 1048575 }
602 #include "gvarargs.h"
615 typedef const void *CPTR_T;
619 #ifdef _STDIO_H_ /* Ultrix 4.0 */
621 typedef void *CPTR_T;
624 typedef char *PTR_T; /* Ultrix 3.1 */
625 typedef char *CPTR_T;
628 #define __proto(x) ()
632 /* Do to size_t being defined in sys/types.h and different
633 in stddef.h, we have to do this by hand..... Note, these
634 types are correct for MIPS based systems, and may not be
635 correct for other systems. Ultrix 4.0 and Silicon Graphics
636 have this fixed, but since the following is correct, and
637 the fact that including stddef.h gets you GCC's version
638 instead of the standard one it's not worth it to fix it. */
640 #define Size_t unsigned int
641 #define Ptrdiff_t int
643 /* The following might be called from obstack or malloc,
644 so they can't be static. */
646 extern void pfatal_with_name
648 extern void fancy_abort __proto((void));
649 extern void botch __proto((const char *));
650 extern PTR_T xmalloc __proto((Size_t));
651 extern PTR_T xcalloc __proto((Size_t, Size_t));
652 extern PTR_T xrealloc __proto((PTR_T, Size_t));
653 extern void xfree __proto((PTR_T));
655 extern PTR_T malloc __proto((Size_t));
656 extern PTR_T calloc __proto((Size_t, Size_t));
657 extern PTR_T realloc __proto((PTR_T, Size_t));
658 extern void free __proto((PTR_T));
660 extern void fatal(); /* can't use prototypes here */
664 #ifndef MIPS_DEBUGGING_INFO
666 static int line_number;
667 static int cur_line_start;
669 static int had_errors;
670 static char *progname;
671 static char *input_name;
676 fprintf (stderr, "Mips-tfile should only be run on a MIPS computer!\n");
680 #else /* MIPS_DEBUGGING defined */
683 #include <sys/types.h>
690 #include <sys/stat.h>
693 extern int errno; /* MIPS errno.h doesn't declare this */
702 #define IS_ASM_IDENT(ch) \
703 (isalnum (ch) || (ch) == '_' || (ch) == '.' || (ch) == '$')
706 /* Redefination of of storage classes as an enumeration for better
710 sc_Nil = scNil, /* no storage class */
711 sc_Text = scText, /* text symbol */
712 sc_Data = scData, /* initialized data symbol */
713 sc_Bss = scBss, /* un-initialized data symbol */
714 sc_Register = scRegister, /* value of symbol is register number */
715 sc_Abs = scAbs, /* value of symbol is absolute */
716 sc_Undefined = scUndefined, /* who knows? */
717 sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
718 sc_Bits = scBits, /* this is a bit field */
719 sc_CdbSystem = scCdbSystem, /* value is IN CDB's address space */
720 sc_RegImage = scRegImage, /* register value saved on stack */
721 sc_Info = scInfo, /* symbol contains debugger information */
722 sc_UserStruct = scUserStruct, /* addr in struct user for current process */
723 sc_SData = scSData, /* load time only small data */
724 sc_SBss = scSBss, /* load time only small common */
725 sc_RData = scRData, /* load time only read only data */
726 sc_Var = scVar, /* Var parameter (fortran,pascal) */
727 sc_Common = scCommon, /* common variable */
728 sc_SCommon = scSCommon, /* small common */
729 sc_VarRegister = scVarRegister, /* Var parameter in a register */
730 sc_Variant = scVariant, /* Variant record */
731 sc_SUndefined = scSUndefined, /* small undefined(external) data */
732 sc_Init = scInit, /* .init section symbol */
733 sc_Max = scMax /* Max storage class+1 */
736 /* Redefinition of symbol type. */
739 st_Nil = stNil, /* Nuthin' special */
740 st_Global = stGlobal, /* external symbol */
741 st_Static = stStatic, /* static */
742 st_Param = stParam, /* procedure argument */
743 st_Local = stLocal, /* local variable */
744 st_Label = stLabel, /* label */
745 st_Proc = stProc, /* " " Procedure */
746 st_Block = stBlock, /* beginnning of block */
747 st_End = stEnd, /* end (of anything) */
748 st_Member = stMember, /* member (of anything - struct/union/enum */
749 st_Typedef = stTypedef, /* type definition */
750 st_File = stFile, /* file name */
751 st_RegReloc = stRegReloc, /* register relocation */
752 st_Forward = stForward, /* forwarding address */
753 st_StaticProc = stStaticProc, /* load time only static procs */
754 st_Constant = stConstant, /* const */
755 st_Str = stStr, /* string */
756 st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
757 st_Expr = stExpr, /* 2+2 vs. 4 */
758 st_Type = stType, /* post-coersion SER */
759 st_Max = stMax /* max type+1 */
762 /* Redefinition of type qualifiers. */
765 tq_Nil = tqNil, /* bt is what you see */
766 tq_Ptr = tqPtr, /* pointer */
767 tq_Proc = tqProc, /* procedure */
768 tq_Array = tqArray, /* duh */
769 tq_Far = tqFar, /* longer addressing - 8086/8 land */
770 tq_Vol = tqVol, /* volatile */
771 tq_Max = tqMax /* Max type qualifier+1 */
774 /* Redefinition of basic types. */
777 bt_Nil = btNil, /* undefined */
778 bt_Adr = btAdr, /* address - integer same size as pointer */
779 bt_Char = btChar, /* character */
780 bt_UChar = btUChar, /* unsigned character */
781 bt_Short = btShort, /* short */
782 bt_UShort = btUShort, /* unsigned short */
783 bt_Int = btInt, /* int */
784 bt_UInt = btUInt, /* unsigned int */
785 bt_Long = btLong, /* long */
786 bt_ULong = btULong, /* unsigned long */
787 bt_Float = btFloat, /* float (real) */
788 bt_Double = btDouble, /* Double (real) */
789 bt_Struct = btStruct, /* Structure (Record) */
790 bt_Union = btUnion, /* Union (variant) */
791 bt_Enum = btEnum, /* Enumerated */
792 bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
793 bt_Range = btRange, /* subrange of int */
794 bt_Set = btSet, /* pascal sets */
795 bt_Complex = btComplex, /* fortran complex */
796 bt_DComplex = btDComplex, /* fortran double complex */
797 bt_Indirect = btIndirect, /* forward or unnamed typedef */
798 bt_FixedDec = btFixedDec, /* Fixed Decimal */
799 bt_FloatDec = btFloatDec, /* Float Decimal */
800 bt_String = btString, /* Varying Length Character String */
801 bt_Bit = btBit, /* Aligned Bit String */
802 bt_Picture = btPicture, /* Picture */
805 bt_Void = btVoid, /* Void */
807 #define bt_Void bt_Nil
810 bt_Max = btMax /* Max basic type+1 */
815 /* Basic COFF storage classes. */
847 /* Regular COFF fundamental type. */
848 typedef enum coff_type {
868 /* Regular COFF derived types. */
869 typedef enum coff_dt {
877 #define N_BTMASK 017 /* bitmask to isolate basic type */
878 #define N_TMASK 003 /* bitmask to isolate derived type */
879 #define N_BT_SHIFT 4 /* # bits to shift past basic type */
880 #define N_TQ_SHIFT 2 /* # bits to shift derived types */
881 #define N_TQ 6 /* # of type qualifiers */
883 /* States for whether to hash type or not. */
884 typedef enum hash_state {
885 hash_no = 0, /* don't hash type */
886 hash_yes = 1, /* ok to hash type, or use previous hash */
887 hash_record = 2 /* ok to record hash, but don't use prev. */
891 #define WORD_ALIGN(x) (((x) + 3) & ~3)
892 #define DWORD_ALIGN(x) (((x) + 7) & ~7)
895 /* Structures to provide n-number of virtual arrays, each of which can
896 grow linearly, and which are written in the object file as sequential
897 pages. On systems with a BSD malloc that define USE_MALLOC, the
898 MAX_CLUSTER_PAGES should be 1 less than a power of two, since malloc
899 adds it's overhead, and rounds up to the next power of 2. Pages are
900 linked together via a linked list.
902 If PAGE_SIZE is > 4096, the string length in the shash_t structure
903 can't be represented (assuming there are strings > 4096 bytes). */
906 #define PAGE_SIZE 4096 /* size of varray pages */
909 #define PAGE_USIZE ((Size_t)PAGE_SIZE)
912 #ifndef MAX_CLUSTER_PAGES /* # pages to get from system */
913 #ifndef USE_MALLOC /* in one memory request */
914 #define MAX_CLUSTER_PAGES 64
916 #define MAX_CLUSTER_PAGES 63
921 /* Linked list connecting separate page allocations. */
922 typedef struct vlinks {
923 struct vlinks *prev; /* previous set of pages */
924 struct vlinks *next; /* next set of pages */
925 union page *datum; /* start of page */
926 unsigned long start_index; /* starting index # of page */
930 /* Virtual array header. */
931 typedef struct varray {
932 vlinks_t *first; /* first page link */
933 vlinks_t *last; /* last page link */
934 unsigned long num_allocated; /* # objects allocated */
935 unsigned short object_size; /* size in bytes of each object */
936 unsigned short objects_per_page; /* # objects that can fit on a page */
937 unsigned short objects_last_page; /* # objects allocated on last page */
941 #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
943 #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
946 #define INIT_VARRAY(type) { /* macro to initialize a varray */ \
947 (vlinks_t *)0, /* first */ \
948 (vlinks_t *)0, /* last */ \
949 0, /* num_allocated */ \
950 sizeof (type), /* object_size */ \
951 OBJECTS_PER_PAGE (type), /* objects_per_page */ \
952 OBJECTS_PER_PAGE (type), /* objects_last_page */ \
955 /* Master type for indexes within the symbol table. */
956 typedef unsigned long symint_t;
959 /* Linked list support for nested scopes (file, block, structure, etc.). */
960 typedef struct scope {
961 struct scope *prev; /* previous scope level */
962 SYMR *lsym; /* pointer to local symbol node */
963 symint_t lnumber; /* lsym index */
964 st_t type; /* type of the node */
968 /* Forward reference list for tags referenced, but not yet defined. */
969 typedef struct forward {
970 struct forward *next; /* next forward reference */
971 AUXU *ifd_ptr; /* pointer to store file index */
972 AUXU *index_ptr; /* pointer to store symbol index */
973 AUXU *type_ptr; /* pointer to munge type info */
977 /* Linked list support for tags. The first tag in the list is always
978 the current tag for that block. */
980 struct shash *hash_ptr; /* pointer to the hash table head */
981 struct tag *same_name; /* tag with same name in outer scope */
982 struct tag *same_block; /* next tag defined in the same block. */
983 struct forward *forward_ref; /* list of forward references */
984 bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
985 symint_t ifd; /* file # tag defined in */
986 symint_t index; /* index within file's local symbols */
989 /* Head of a block's linked list of tags. */
990 typedef struct thead {
991 struct thead *prev; /* previous block */
992 struct tag *first_tag; /* first tag in block defined */
996 /* String hash table support. The size of the hash table must fit
1001 #define SHASH_SIZE 1009
1004 #define HASH_LEN_MAX ((1 << 12) - 1) /* Max length we can store */
1006 typedef struct shash {
1007 struct shash *next; /* next hash value */
1008 char *string; /* string we are hashing */
1009 symint_t len; /* string length */
1010 symint_t index; /* index within string table */
1011 EXTR *esym_ptr; /* global symbol pointer */
1012 SYMR *sym_ptr; /* local symbol pointer */
1013 tag_t *tag_ptr; /* tag pointer */
1014 PDR *proc_ptr; /* procedure descriptor pointer */
1018 /* Type hash table support. The size of the hash table must fit
1019 within a page with the other extended file descriptor information.
1020 Because unique types which are hashed are fewer in number than
1021 strings, we use a smaller hash value. */
1024 #define THASH_SIZE 113
1027 typedef struct thash {
1028 struct thash *next; /* next hash value */
1029 AUXU type; /* type we are hashing */
1030 symint_t index; /* index within string table */
1034 /* Union of various small structures that are allocated and freed
1035 from the same heap. */
1037 typedef union word8 {
1038 union word8 *prev; /* previous word8 structure */
1039 scope_t s; /* scope structure */
1040 vlinks_t v; /* varray linked list */
1041 shash_t sh; /* string hash linked list */
1042 thash_t th; /* type hash linked list */
1043 tag_t t; /* tag structure */
1044 forward_t f; /* forward tag references */
1045 thead_t thead; /* thead strcture */
1046 long words[8]; /* words to zero out when allocating */
1050 /* Extended file descriptor that contains all of the support necessary
1051 to add things to each file separately. */
1052 typedef struct efdr {
1053 FDR fdr; /* File header to be written out */
1054 FDR *orig_fdr; /* original file header */
1055 char *name; /* filename */
1056 int name_len; /* length of the filename */
1057 symint_t void_type; /* aux. pointer to 'void' type */
1058 symint_t int_type; /* aux. pointer to 'int' type */
1059 scope_t *cur_scope; /* current nested scopes */
1060 symint_t file_index; /* current file number */
1061 int nested_scopes; /* # nested scopes */
1062 varray_t strings; /* local strings */
1063 varray_t symbols; /* local symbols */
1064 varray_t procs; /* procedures */
1065 varray_t aux_syms; /* auxiliary symbols */
1067 struct efdr *next_file; /* next file descriptor */
1069 /* string/type hash tables */
1070 shash_t **shash_head; /* string hash table */
1071 thash_t *thash_head[THASH_SIZE];
1074 /* Pre-initialized extended file structure. */
1075 static efdr_t init_file =
1077 { /* FDR structure */
1078 0, /* adr: memory address of beginning of file */
1079 0, /* rss: file name (of source, if known) */
1080 0, /* issBase: file's string space */
1081 0, /* cbSs: number of bytes in the ss */
1082 0, /* isymBase: beginning of symbols */
1083 0, /* csym: count file's of symbols */
1084 0, /* ilineBase: file's line symbols */
1085 0, /* cline: count of file's line symbols */
1086 0, /* ioptBase: file's optimization entries */
1087 0, /* copt: count of file's optimization entries */
1088 0, /* ipdFirst: start of procedures for this file */
1089 0, /* cpd: count of procedures for this file */
1090 0, /* iauxBase: file's auxiliary entries */
1091 0, /* caux: count of file's auxiliary entries */
1092 0, /* rfdBase: index into the file indirect table */
1093 0, /* crfd: count file indirect entries */
1094 langC, /* lang: language for this file */
1095 1, /* fMerge: whether this file can be merged */
1096 0, /* fReadin: true if read in (not just created) */
1097 #ifdef BYTES_BIG_ENDIAN
1098 1, /* fBigendian: if 1, compiled on big endian machine */
1100 0, /* fBigendian: if 1, compiled on big endian machine */
1102 GLEVEL_2, /* glevel: level this file was compiled with */
1103 0, /* reserved: reserved for future use */
1104 0, /* cbLineOffset: byte offset from header for this file ln's */
1105 0, /* cbLine: size of lines for this file */
1108 (FDR *)0, /* orig_fdr: original file header pointer */
1109 (char *)0, /* name: pointer to filename */
1110 0, /* name_len: length of filename */
1111 0, /* void_type: ptr to aux node for void type */
1112 0, /* int_type: ptr to aux node for int type */
1113 (scope_t *)0, /* cur_scope: current scope being processed */
1114 0, /* file_index: current file # */
1115 0, /* nested_scopes: # nested scopes */
1116 INIT_VARRAY (char), /* strings: local string varray */
1117 INIT_VARRAY (SYMR), /* symbols: local symbols varray */
1118 INIT_VARRAY (PDR), /* procs: procedure varray */
1119 INIT_VARRAY (AUXU), /* aux_syms: auxiliary symbols varray */
1121 (struct efdr *)0, /* next_file: next file structure */
1123 (shash_t **)0, /* shash_head: string hash table */
1124 { 0 }, /* thash_head: type hash table */
1128 static efdr_t *first_file; /* first file descriptor */
1129 static efdr_t *last_file; /* last file descriptor */
1132 /* Union of various things that are held in pages. */
1133 typedef union page {
1134 char byte [ PAGE_SIZE ];
1135 unsigned char ubyte[ PAGE_SIZE ];
1136 efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
1137 FDR ofile[ PAGE_SIZE / sizeof (FDR) ];
1138 PDR proc [ PAGE_SIZE / sizeof (PDR) ];
1139 SYMR sym [ PAGE_SIZE / sizeof (SYMR) ];
1140 EXTR esym [ PAGE_SIZE / sizeof (EXTR) ];
1141 AUXU aux [ PAGE_SIZE / sizeof (AUXU) ];
1142 DNR dense[ PAGE_SIZE / sizeof (DNR) ];
1143 word8_t word8[ PAGE_SIZE / sizeof (word8_t) ];
1147 /* Type information collected together. */
1148 typedef struct type_info {
1149 bt_t basic_type; /* basic type */
1150 coff_type_t orig_type; /* original COFF-based type */
1151 int num_tq; /* # type qualifiers */
1152 int num_dims; /* # dimensions */
1153 int num_sizes; /* # sizes */
1154 int extra_sizes; /* # extra sizes not tied with dims */
1155 tag_t * tag_ptr; /* tag pointer */
1156 int bitfield; /* symbol is a bitfield */
1157 int unknown_tag; /* this is an unknown tag */
1158 tq_t type_qualifiers[N_TQ]; /* type qualifiers (ptr, func, array)*/
1159 symint_t dimensions [N_TQ]; /* dimensions for each array */
1160 symint_t sizes [N_TQ+2]; /* sizes of each array slice + size of
1161 struct/union/enum + bitfield size */
1164 /* Pre-initialized type_info struct. */
1165 static type_info_t type_info_init = {
1166 bt_Nil, /* basic type */
1167 T_NULL, /* original COFF-based type */
1168 0, /* # type qualifiers */
1169 0, /* # dimensions */
1171 0, /* sizes not tied with dims */
1172 NULL, /* ptr to tag */
1174 0, /* unknown tag */
1175 { /* type qualifiers */
1204 /* Global virtual arrays & hash table for external strings as well as
1205 for the tags table and global tables for file descriptors, and
1208 static varray_t file_desc = INIT_VARRAY (efdr_t);
1209 static varray_t dense_num = INIT_VARRAY (DNR);
1210 static varray_t tag_strings = INIT_VARRAY (char);
1211 static varray_t ext_strings = INIT_VARRAY (char);
1212 static varray_t ext_symbols = INIT_VARRAY (EXTR);
1214 static shash_t *orig_str_hash[SHASH_SIZE];
1215 static shash_t *ext_str_hash [SHASH_SIZE];
1216 static shash_t *tag_hash [SHASH_SIZE];
1218 /* Static types for int and void. Also, remember the last function's
1219 type (which is set up when we encounter the declaration for the
1220 function, and used when the end block for the function is emitted. */
1222 static type_info_t int_type_info;
1223 static type_info_t void_type_info;
1224 static type_info_t last_func_type_info;
1225 static EXTR *last_func_eptr;
1228 /* Convert COFF basic type to ECOFF basic type. The T_NULL type
1229 really should use bt_Void, but this causes the current ecoff GDB to
1230 issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
1231 2.0) doesn't understand it, even though the compiler generates it.
1232 Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
1233 suite, but for now go with what works. */
1235 static bt_t map_coff_types[ (int)T_MAX ] = {
1236 bt_Nil, /* T_NULL */
1238 bt_Char, /* T_CHAR */
1239 bt_Short, /* T_SHORT */
1241 bt_Long, /* T_LONG */
1242 bt_Float, /* T_FLOAT */
1243 bt_Double, /* T_DOUBLE */
1244 bt_Struct, /* T_STRUCT */
1245 bt_Union, /* T_UNION */
1246 bt_Enum, /* T_ENUM */
1247 bt_Enum, /* T_MOE */
1248 bt_UChar, /* T_UCHAR */
1249 bt_UShort, /* T_USHORT */
1250 bt_UInt, /* T_UINT */
1251 bt_ULong /* T_ULONG */
1254 /* Convert COFF storage class to ECOFF storage class. */
1255 static sc_t map_coff_storage[ (int)C_MAX ] = {
1256 sc_Nil, /* 0: C_NULL */
1257 sc_Abs, /* 1: C_AUTO auto var */
1258 sc_Undefined, /* 2: C_EXT external */
1259 sc_Data, /* 3: C_STAT static */
1260 sc_Register, /* 4: C_REG register */
1261 sc_Undefined, /* 5: C_EXTDEF ??? */
1262 sc_Text, /* 6: C_LABEL label */
1263 sc_Text, /* 7: C_ULABEL user label */
1264 sc_Info, /* 8: C_MOS member of struct */
1265 sc_Abs, /* 9: C_ARG argument */
1266 sc_Info, /* 10: C_STRTAG struct tag */
1267 sc_Info, /* 11: C_MOU member of union */
1268 sc_Info, /* 12: C_UNTAG union tag */
1269 sc_Info, /* 13: C_TPDEF typedef */
1270 sc_Data, /* 14: C_USTATIC ??? */
1271 sc_Info, /* 15: C_ENTAG enum tag */
1272 sc_Info, /* 16: C_MOE member of enum */
1273 sc_Register, /* 17: C_REGPARM register parameter */
1274 sc_Bits, /* 18; C_FIELD bitfield */
1356 sc_Text, /* 100: C_BLOCK block start/end */
1357 sc_Text, /* 101: C_FCN function start/end */
1358 sc_Info, /* 102: C_EOS end of struct/union/enum */
1359 sc_Nil, /* 103: C_FILE file start */
1360 sc_Nil, /* 104: C_LINE line number */
1361 sc_Nil, /* 105: C_ALIAS combined type info */
1362 sc_Nil, /* 106: C_HIDDEN ??? */
1365 /* Convert COFF storage class to ECOFF symbol type. */
1366 static st_t map_coff_sym_type[ (int)C_MAX ] = {
1367 st_Nil, /* 0: C_NULL */
1368 st_Local, /* 1: C_AUTO auto var */
1369 st_Global, /* 2: C_EXT external */
1370 st_Static, /* 3: C_STAT static */
1371 st_Local, /* 4: C_REG register */
1372 st_Global, /* 5: C_EXTDEF ??? */
1373 st_Label, /* 6: C_LABEL label */
1374 st_Label, /* 7: C_ULABEL user label */
1375 st_Member, /* 8: C_MOS member of struct */
1376 st_Param, /* 9: C_ARG argument */
1377 st_Block, /* 10: C_STRTAG struct tag */
1378 st_Member, /* 11: C_MOU member of union */
1379 st_Block, /* 12: C_UNTAG union tag */
1380 st_Typedef, /* 13: C_TPDEF typedef */
1381 st_Static, /* 14: C_USTATIC ??? */
1382 st_Block, /* 15: C_ENTAG enum tag */
1383 st_Member, /* 16: C_MOE member of enum */
1384 st_Param, /* 17: C_REGPARM register parameter */
1385 st_Member, /* 18; C_FIELD bitfield */
1467 st_Block, /* 100: C_BLOCK block start/end */
1468 st_Proc, /* 101: C_FCN function start/end */
1469 st_End, /* 102: C_EOS end of struct/union/enum */
1470 st_File, /* 103: C_FILE file start */
1471 st_Nil, /* 104: C_LINE line number */
1472 st_Nil, /* 105: C_ALIAS combined type info */
1473 st_Nil, /* 106: C_HIDDEN ??? */
1476 /* Map COFF derived types to ECOFF type qualifiers. */
1477 static tq_t map_coff_derived_type[ (int)DT_MAX ] = {
1478 tq_Nil, /* 0: DT_NON no more qualifiers */
1479 tq_Ptr, /* 1: DT_PTR pointer */
1480 tq_Proc, /* 2: DT_FCN function */
1481 tq_Array, /* 3: DT_ARY array */
1486 /* Pointers and such to the original symbol table that is read in. */
1487 static struct filehdr orig_file_header; /* global object file header */
1489 static HDRR orig_sym_hdr; /* symbolic header on input */
1490 static char *orig_linenum; /* line numbers */
1491 static DNR *orig_dense; /* dense numbers */
1492 static PDR *orig_procs; /* procedures */
1493 static SYMR *orig_local_syms; /* local symbols */
1494 static OPTR *orig_opt_syms; /* optimization symbols */
1495 static AUXU *orig_aux_syms; /* auxiliary symbols */
1496 static char *orig_local_strs; /* local strings */
1497 static char *orig_ext_strs; /* external strings */
1498 static FDR *orig_files; /* file descriptors */
1499 static symint_t *orig_rfds; /* relative file desc's */
1500 static EXTR *orig_ext_syms; /* external symbols */
1502 /* Macros to convert an index into a given object within the original
1504 #define CHECK(num,max,str) \
1505 (((unsigned long)num > (unsigned long)max) ? out_of_bounds (num, max, str, __LINE__) : 0)
1507 #define ORIG_LINENUM(index) (CHECK ((index), orig_sym_hdr.cbLine, "line#"), (index) + orig_linenum)
1508 #define ORIG_DENSE(index) (CHECK ((index), orig_sym_hdr.idnMax, "dense"), (index) + orig_dense)
1509 #define ORIG_PROCS(index) (CHECK ((index), orig_sym_hdr.ipdMax, "procs"), (index) + orig_procs)
1510 #define ORIG_FILES(index) (CHECK ((index), orig_sym_hdr.ifdMax, "funcs"), (index) + orig_files)
1511 #define ORIG_LSYMS(index) (CHECK ((index), orig_sym_hdr.isymMax, "lsyms"), (index) + orig_local_syms)
1512 #define ORIG_LSTRS(index) (CHECK ((index), orig_sym_hdr.issMax, "lstrs"), (index) + orig_local_strs)
1513 #define ORIG_ESYMS(index) (CHECK ((index), orig_sym_hdr.iextMax, "esyms"), (index) + orig_ext_syms)
1514 #define ORIG_ESTRS(index) (CHECK ((index), orig_sym_hdr.issExtMax, "estrs"), (index) + orig_ext_strs)
1515 #define ORIG_OPT(index) (CHECK ((index), orig_sym_hdr.ioptMax, "opt"), (index) + orig_opt_syms)
1516 #define ORIG_AUX(index) (CHECK ((index), orig_sym_hdr.iauxMax, "aux"), (index) + orig_aux_syms)
1517 #define ORIG_RFDS(index) (CHECK ((index), orig_sym_hdr.crfd, "rfds"), (index) + orig_rfds)
1519 /* Various other statics. */
1520 static HDRR symbolic_header; /* symbolic header */
1521 static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */
1522 static PDR *cur_proc_ptr = (PDR *) 0; /* current procedure header */
1523 static PDR *cur_oproc_ptr = (PDR *) 0; /* current original procedure*/
1524 static thead_t *cur_tag_head = (thead_t *)0; /* current tag head */
1525 static long file_offset = 0; /* current file offset */
1526 static long max_file_offset = 0; /* maximum file offset */
1527 static FILE *object_stream = (FILE *)0; /* file desc. to output .o */
1528 static FILE *obj_in_stream = (FILE *)0; /* file desc. to input .o */
1529 static char *progname = (char *)0; /* program name for errors */
1530 static char *input_name = "stdin"; /* name of input file */
1531 static char *object_name = (char *)0; /* tmp. name of object file */
1532 static char *obj_in_name = (char *)0; /* name of input object file */
1533 static char *cur_line_start = (char *)0; /* current line read in */
1534 static char *cur_line_ptr = (char *)0; /* ptr within current line */
1535 static unsigned cur_line_nbytes = 0; /* # bytes for current line */
1536 static unsigned cur_line_alloc = 0; /* # bytes total in buffer */
1537 static long line_number = 0; /* current input line number */
1538 static int debug = 0; /* trace functions */
1539 static int version = 0; /* print version # */
1540 static int had_errors = 0; /* != 0 if errors were found */
1541 static int rename_output = 0; /* != 0 if rename output file*/
1542 static int delete_input = 0; /* != 0 if delete input after done */
1545 /* Forward reference for functions. See the definition for more details. */
1548 #define STATIC static
1551 STATIC int out_of_bounds __proto((symint_t, symint_t, const char *, int));
1553 STATIC shash_t *hash_string __proto((const char *,
1558 STATIC symint_t add_string __proto((varray_t *,
1564 STATIC symint_t add_local_symbol
1565 __proto((const char *,
1572 STATIC symint_t add_ext_symbol __proto((const char *,
1580 STATIC symint_t add_aux_sym_symint
1581 __proto((symint_t));
1583 STATIC symint_t add_aux_sym_rndx
1584 __proto((int, symint_t));
1586 STATIC symint_t add_aux_sym_tir __proto((type_info_t *,
1590 STATIC tag_t * get_tag __proto((const char *,
1595 STATIC void add_unknown_tag __proto((tag_t *));
1597 STATIC void add_procedure __proto((const char *,
1600 STATIC void add_file __proto((const char *,
1603 STATIC void add_bytes __proto((varray_t *,
1607 STATIC void add_varray_page __proto((varray_t *));
1609 STATIC void update_headers __proto((void));
1611 STATIC void write_varray __proto((varray_t *, off_t, const char *));
1612 STATIC void write_object __proto((void));
1613 STATIC char *st_to_string __proto((st_t));
1614 STATIC char *sc_to_string __proto((sc_t));
1615 STATIC char *read_line __proto((void));
1616 STATIC void parse_input __proto((void));
1617 STATIC void parse_begin __proto((const char *));
1618 STATIC void parse_bend __proto((const char *));
1619 STATIC void parse_def __proto((const char *));
1620 STATIC void parse_end __proto((const char *));
1621 STATIC void parse_ent __proto((const char *));
1622 STATIC void parse_file __proto((const char *));
1623 STATIC page_t *read_seek __proto((Size_t, off_t, const char *));
1624 STATIC void copy_object __proto((void));
1626 STATIC void catch_signal __proto((int));
1627 STATIC page_t *allocate_page __proto((void));
1629 STATIC page_t *allocate_multiple_pages
1632 STATIC void free_multiple_pages
1633 __proto((page_t *, Size_t));
1635 #ifndef MALLOC_CHECK
1636 STATIC page_t *allocate_cluster
1640 STATIC word8_t *allocate_word8 __proto((void));
1641 STATIC void free_word8 __proto((word8_t *));
1644 /* Prototypes for library functions used. */
1645 #if !defined(NO_LIB_PROTOTYPE) && !defined(_OSF_SOURCE) && !defined(_STDIO_H_)
1646 extern char *strchr __proto((const char *, int));
1647 extern char *strrchr __proto((const char *, int));
1648 extern int strcmp __proto((const char *, const char *));
1649 extern long strtol __proto((const char *, char **, int));
1650 extern int memcmp __proto((CPTR_T, CPTR_T, Size_t));
1651 extern time_t time __proto((time_t *));
1652 extern int fputc __proto((int, FILE *));
1653 extern int vprintf __proto((const char *, va_list));
1654 extern int vfprintf __proto((FILE *, const char *, va_list));
1655 extern int vsprintf __proto((char *, const char *, va_list));
1656 extern int fclose __proto((FILE *));
1657 extern int fseek __proto((FILE *, long, int));
1658 extern long ftell __proto((FILE *));
1659 extern FILE *fopen __proto((const char *, const char *));
1660 extern FILE *freopen __proto((const char *, const char *, FILE *));
1661 extern int fflush __proto((FILE *));
1662 extern void perror __proto((const char *));
1663 extern void exit __proto((int));
1664 extern int open __proto((const char *, int, ...));
1665 extern int rename __proto((const char *, const char *));
1668 extern int setvbuf __proto((FILE *, char *, int, int));
1669 extern int fputs __proto((char *, FILE *));
1672 #ifndef NO_LIB_INTERNALS
1673 extern int _filbuf __proto((FILE *));
1674 extern int _flsbuf __proto((int, FILE *));
1678 extern char *sbrk __proto((int));
1679 extern PTR_T malloc __proto((Size_t));
1680 extern PTR_T calloc __proto((Size_t, Size_t));
1681 extern PTR_T realloc __proto((PTR_T, Size_t));
1682 extern void free __proto((PTR_T));
1683 extern int close __proto((int));
1684 extern int write __proto((int, CPTR_T, Size_t));
1685 extern int read __proto((int, PTR_T, Size_t));
1686 extern long lseek __proto((int, long, int));
1687 extern int ftruncate __proto((int, long));
1688 extern int getopt __proto((int, char **, const char *));
1689 extern int fstat __proto((int, struct stat *));
1690 extern char *mktemp __proto((char *));
1692 extern char *optarg;
1696 #ifndef SEEK_SET /* Symbolic constants for the "fseek" function: */
1697 #define SEEK_SET 0 /* Set file pointer to offset */
1698 #define SEEK_CUR 1 /* Set file pointer to its current value plus offset */
1699 #define SEEK_END 2 /* Set file pointer to the size of the file plus offset */
1703 /* List of assembler pseudo ops and beginning sequences that need
1704 special actions. Someday, this should be a hash table, and such,
1705 but for now a linear list of names and calls to memcmp will
1708 typedef struct _pseudo_ops {
1709 const char *name; /* pseduo-op in ascii */
1710 int len; /* length of name to compare */
1711 void (*func) __proto((const char *)); /* function to handle line */
1714 static pseudo_ops_t pseudo_ops[] = {
1715 { "#.def", sizeof("#.def")-1, parse_def },
1716 { "#.begin", sizeof("#.begin")-1, parse_begin },
1717 { "#.bend", sizeof("#.bend")-1, parse_bend },
1718 { ".end", sizeof(".end")-1, parse_end },
1719 { ".ent", sizeof(".ent")-1, parse_ent },
1720 { ".file", sizeof(".file")-1, parse_file },
1724 /* Add a page to a varray object. */
1727 add_varray_page (vp)
1728 varray_t *vp; /* varray to add page to */
1730 vlinks_t *new_links = (vlinks_t *) allocate_word8 ();
1733 if (vp->object_size > 1)
1734 new_links->datum = (page_t *) xcalloc (1, vp->object_size);
1737 new_links->datum = allocate_page ();
1739 new_links->start_index = vp->num_allocated;
1740 vp->objects_last_page = 0;
1742 if (vp->first == (vlinks_t *)0) /* first allocation? */
1743 vp->first = vp->last = new_links;
1745 { /* 2nd or greater allocation */
1746 new_links->prev = vp->last;
1747 vp->last->next = new_links;
1748 vp->last = new_links;
1753 /* Compute hash code (from tree.c) */
1758 hash_string (text, hash_len, hash_tbl, ret_hash_index)
1759 const char *text; /* ptr to text to hash */
1760 Ptrdiff_t hash_len; /* length of the text */
1761 shash_t **hash_tbl; /* hash table */
1762 symint_t *ret_hash_index; /* ptr to store hash index */
1764 register unsigned long hi;
1765 register Ptrdiff_t i;
1766 register shash_t *ptr;
1767 register int first_ch = *text;
1770 for (i = 0; i < hash_len; i++)
1771 hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
1773 hi &= (1 << HASHBITS) - 1;
1776 if (ret_hash_index != (symint_t *)0)
1777 *ret_hash_index = hi;
1779 for (ptr = hash_tbl[hi]; ptr != (shash_t *)0; ptr = ptr->next)
1780 if (hash_len == ptr->len
1781 && first_ch == ptr->string[0]
1782 && memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
1789 /* Add a string (and null pad) to one of the string tables. A
1790 consequence of hashing strings, is that we don't let strings
1791 cross page boundaries. The extra nulls will be ignored. */
1794 add_string (vp, hash_tbl, start, end_p1, ret_hash)
1795 varray_t *vp; /* string virtual array */
1796 shash_t **hash_tbl; /* ptr to hash table */
1797 const char *start; /* 1st byte in string */
1798 const char *end_p1; /* 1st byte after string */
1799 shash_t **ret_hash; /* return hash pointer */
1801 register Ptrdiff_t len = end_p1 - start;
1802 register shash_t *hash_ptr;
1805 if (len >= PAGE_USIZE)
1806 fatal ("String too big (%ld bytes)", (long) len);
1808 hash_ptr = hash_string (start, len, hash_tbl, &hi);
1809 if (hash_ptr == (shash_t *)0)
1813 if (vp->objects_last_page + len >= PAGE_USIZE)
1816 ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
1817 add_varray_page (vp);
1820 hash_ptr = (shash_t *) allocate_word8 ();
1821 hash_ptr->next = hash_tbl[hi];
1822 hash_tbl[hi] = hash_ptr;
1824 hash_ptr->len = len;
1825 hash_ptr->index = vp->num_allocated;
1826 hash_ptr->string = p =
1827 & vp->last->datum->byte[ vp->objects_last_page ];
1829 vp->objects_last_page += len+1;
1830 vp->num_allocated += len+1;
1838 if (ret_hash != (shash_t **)0)
1839 *ret_hash = hash_ptr;
1841 return hash_ptr->index;
1845 /* Add a local symbol. */
1848 add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
1849 const char *str_start; /* first byte in string */
1850 const char *str_end_p1; /* first byte after string */
1851 st_t type; /* symbol type */
1852 sc_t storage; /* storage class */
1853 symint_t value; /* value of symbol */
1854 symint_t indx; /* index to local/aux. syms */
1856 register symint_t ret;
1857 register SYMR *psym;
1858 register scope_t *pscope;
1859 register thead_t *ptag_head;
1860 register tag_t *ptag;
1861 register tag_t *ptag_next;
1862 register varray_t *vp = &cur_file_ptr->symbols;
1863 register int scope_delta = 0;
1864 shash_t *hash_ptr = (shash_t *)0;
1866 if (vp->objects_last_page == vp->objects_per_page)
1867 add_varray_page (vp);
1869 psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
1871 psym->value = value;
1872 psym->st = (unsigned) type;
1873 psym->sc = (unsigned) storage;
1875 psym->iss = (str_start == (const char *)0)
1877 : add_string (&cur_file_ptr->strings,
1878 &cur_file_ptr->shash_head[0],
1883 ret = vp->num_allocated++;
1885 /* Save the symbol within the hash table if this is a static
1887 if (type == st_Global || type == st_Static || type == st_Label
1888 || type == st_Proc || type == st_StaticProc)
1889 hash_ptr->sym_ptr = psym;
1891 /* push or pop a scope if appropriate. */
1897 case st_File: /* beginning of file */
1898 case st_Proc: /* procedure */
1899 case st_StaticProc: /* static procedure */
1900 case st_Block: /* begin scope */
1901 pscope = (scope_t *) allocate_word8 ();
1902 pscope->prev = cur_file_ptr->cur_scope;
1903 pscope->lsym = psym;
1904 pscope->lnumber = ret;
1905 pscope->type = type;
1906 cur_file_ptr->cur_scope = pscope;
1908 if (type != st_File)
1911 /* For every block type except file, struct, union, or
1912 enumeration blocks, push a level on the tag stack. We omit
1913 file types, so that tags can span file boundaries. */
1914 if (type != st_File && storage != sc_Info)
1916 ptag_head = (thead_t *) allocate_word8 ();
1917 ptag_head->first_tag = 0;
1918 ptag_head->prev = cur_tag_head;
1919 cur_tag_head = ptag_head;
1924 pscope = cur_file_ptr->cur_scope;
1925 if (pscope == (scope_t *)0)
1926 error ("internal error, too many st_End's");
1930 st_t begin_type = (st_t) pscope->lsym->st;
1932 if (begin_type != st_File)
1935 /* Except for file, structure, union, or enumeration end
1936 blocks remove all tags created within this scope. */
1937 if (begin_type != st_File && storage != sc_Info)
1939 ptag_head = cur_tag_head;
1940 cur_tag_head = ptag_head->prev;
1942 for (ptag = ptag_head->first_tag;
1946 if (ptag->forward_ref != (forward_t *)0)
1947 add_unknown_tag (ptag);
1949 ptag_next = ptag->same_block;
1950 ptag->hash_ptr->tag_ptr = ptag->same_name;
1951 free_word8 ((word8_t *) ptag);
1954 free_word8 ((word8_t *) ptag_head);
1957 cur_file_ptr->cur_scope = pscope->prev;
1958 psym->index = pscope->lnumber; /* blk end gets begin sym # */
1960 if (storage != sc_Info)
1961 psym->iss = pscope->lsym->iss; /* blk end gets same name */
1963 if (begin_type == st_File || begin_type == st_Block)
1964 pscope->lsym->index = ret+1; /* block begin gets next sym # */
1966 /* Functions push two or more aux words as follows:
1967 1st word: index+1 of the end symbol
1968 2nd word: type of the function (plus any aux words needed).
1969 Also, tie the external pointer back to the function begin symbol. */
1973 pscope->lsym->index = add_aux_sym_symint (ret+1);
1974 type = add_aux_sym_tir (&last_func_type_info,
1976 &cur_file_ptr->thash_head[0]);
1979 last_func_eptr->ifd = cur_file_ptr->file_index;
1980 last_func_eptr->asym.index = type;
1984 free_word8 ((word8_t *) pscope);
1988 cur_file_ptr->nested_scopes += scope_delta;
1990 if (debug && type != st_File
1991 && (debug > 2 || type == st_Block || type == st_End
1992 || type == st_Proc || type == st_StaticProc))
1994 char *sc_str = sc_to_string (storage);
1995 char *st_str = st_to_string (type);
1996 int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
1999 "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
2000 value, depth, sc_str);
2002 if (str_start && str_end_p1 - str_start > 0)
2003 fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2006 Size_t len = strlen (st_str);
2007 fprintf (stderr, " st= %.*s\n", len-1, st_str);
2015 /* Add an external symbol. */
2018 add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
2019 const char *str_start; /* first byte in string */
2020 const char *str_end_p1; /* first byte after string */
2021 st_t type; /* symbol type */
2022 sc_t storage; /* storage class */
2023 long value; /* value of symbol */
2024 symint_t indx; /* index to local/aux. syms */
2025 int ifd; /* file index */
2027 register EXTR *psym;
2028 register varray_t *vp = &ext_symbols;
2029 shash_t *hash_ptr = (shash_t *)0;
2033 char *sc_str = sc_to_string (storage);
2034 char *st_str = st_to_string (type);
2037 "\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
2038 value, ifd, sc_str);
2040 if (str_start && str_end_p1 - str_start > 0)
2041 fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2043 fprintf (stderr, " st= %s\n", st_str);
2046 if (vp->objects_last_page == vp->objects_per_page)
2047 add_varray_page (vp);
2049 psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
2052 psym->asym.value = value;
2053 psym->asym.st = (unsigned) type;
2054 psym->asym.sc = (unsigned) storage;
2055 psym->asym.index = indx;
2056 psym->asym.iss = (str_start == (const char *)0)
2058 : add_string (&ext_strings,
2064 hash_ptr->esym_ptr = psym;
2065 return vp->num_allocated++;
2069 /* Add an auxiliary symbol (passing a symint). */
2072 add_aux_sym_symint (aux_word)
2073 symint_t aux_word; /* auxilary information word */
2075 register AUXU *aux_ptr;
2076 register efdr_t *file_ptr = cur_file_ptr;
2077 register varray_t *vp = &file_ptr->aux_syms;
2079 if (vp->objects_last_page == vp->objects_per_page)
2080 add_varray_page (vp);
2082 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2083 aux_ptr->isym = aux_word;
2085 return vp->num_allocated++;
2089 /* Add an auxiliary symbol (passing a file/symbol index combo). */
2092 add_aux_sym_rndx (file_index, sym_index)
2096 register AUXU *aux_ptr;
2097 register efdr_t *file_ptr = cur_file_ptr;
2098 register varray_t *vp = &file_ptr->aux_syms;
2100 if (vp->objects_last_page == vp->objects_per_page)
2101 add_varray_page (vp);
2103 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2104 aux_ptr->rndx.rfd = file_index;
2105 aux_ptr->rndx.index = sym_index;
2107 return vp->num_allocated++;
2111 /* Add an auxiliary symbol (passing the basic type and possibly
2112 type qualifiers). */
2115 add_aux_sym_tir (t, state, hash_tbl)
2116 type_info_t *t; /* current type information */
2117 hash_state_t state; /* whether to hash type or not */
2118 thash_t **hash_tbl; /* pointer to hash table to use */
2120 register AUXU *aux_ptr;
2121 register efdr_t *file_ptr = cur_file_ptr;
2122 register varray_t *vp = &file_ptr->aux_syms;
2123 static AUXU init_aux;
2129 aux.ti.bt = (int) t->basic_type;
2130 aux.ti.continued = 0;
2131 aux.ti.fBitfield = t->bitfield;
2133 aux.ti.tq0 = (int) t->type_qualifiers[0];
2134 aux.ti.tq1 = (int) t->type_qualifiers[1];
2135 aux.ti.tq2 = (int) t->type_qualifiers[2];
2136 aux.ti.tq3 = (int) t->type_qualifiers[3];
2137 aux.ti.tq4 = (int) t->type_qualifiers[4];
2138 aux.ti.tq5 = (int) t->type_qualifiers[5];
2141 /* For anything that adds additional information, we must not hash,
2142 so check here, and reset our state. */
2144 if (state != hash_no
2145 && (t->type_qualifiers[0] == tq_Array
2146 || t->type_qualifiers[1] == tq_Array
2147 || t->type_qualifiers[2] == tq_Array
2148 || t->type_qualifiers[3] == tq_Array
2149 || t->type_qualifiers[4] == tq_Array
2150 || t->type_qualifiers[5] == tq_Array
2151 || t->basic_type == bt_Struct
2152 || t->basic_type == bt_Union
2153 || t->basic_type == bt_Enum
2155 || t->num_dims > 0))
2158 /* See if we can hash this type, and save some space, but some types
2159 can't be hashed (because they contain arrays or continuations),
2160 and others can be put into the hash list, but cannot use existing
2161 types because other aux entries precede this one. */
2163 if (state != hash_no)
2165 register thash_t *hash_ptr;
2166 register symint_t hi;
2168 hi = aux.isym & ((1 << HASHBITS) - 1);
2171 for (hash_ptr = hash_tbl[hi];
2172 hash_ptr != (thash_t *)0;
2173 hash_ptr = hash_ptr->next)
2175 if (aux.isym == hash_ptr->type.isym)
2179 if (hash_ptr != (thash_t *)0 && state == hash_yes)
2180 return hash_ptr->index;
2182 if (hash_ptr == (thash_t *)0)
2184 hash_ptr = (thash_t *) allocate_word8 ();
2185 hash_ptr->next = hash_tbl[hi];
2186 hash_ptr->type = aux;
2187 hash_ptr->index = vp->num_allocated;
2188 hash_tbl[hi] = hash_ptr;
2192 /* Everything is set up, add the aux symbol. */
2193 if (vp->objects_last_page == vp->objects_per_page)
2194 add_varray_page (vp);
2196 aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2199 ret = vp->num_allocated++;
2201 /* Add tag information if needed. Structure, union, and enum
2202 references add 2 aux symbols: a [file index, symbol index]
2203 pointer to the structure type, and the current file index. */
2205 if (t->basic_type == bt_Struct
2206 || t->basic_type == bt_Union
2207 || t->basic_type == bt_Enum)
2209 register symint_t file_index = t->tag_ptr->ifd;
2210 register symint_t sym_index = t->tag_ptr->index;
2214 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2215 (void) add_aux_sym_symint ((symint_t)-1);
2217 else if (sym_index != indexNil)
2219 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2220 (void) add_aux_sym_symint (file_index);
2224 register forward_t *forward_ref = (forward_t *) allocate_word8 ();
2226 forward_ref->type_ptr = aux_ptr;
2227 forward_ref->next = t->tag_ptr->forward_ref;
2228 t->tag_ptr->forward_ref = forward_ref;
2230 (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2231 forward_ref->index_ptr
2232 = &vp->last->datum->aux[ vp->objects_last_page - 1];
2234 (void) add_aux_sym_symint (file_index);
2235 forward_ref->ifd_ptr
2236 = &vp->last->datum->aux[ vp->objects_last_page - 1];
2240 /* Add bitfield length if it exists. */
2242 (void) add_aux_sym_symint ((symint_t)t->sizes[0]);
2245 /* Add information about array bounds if they exist. */
2246 for (i = 0; i < t->num_dims; i++)
2248 (void) add_aux_sym_rndx (ST_RFDESCAPE,
2249 cur_file_ptr->int_type);
2251 (void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/
2252 (void) add_aux_sym_symint ((symint_t)0); /* low bound */
2253 (void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/
2254 (void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */
2256 : (t->sizes[i] * 8) / t->dimensions[i]);
2263 /* Add a tag to the tag table (unless it already exists). */
2266 get_tag (tag_start, tag_end_p1, index, basic_type)
2267 const char *tag_start; /* 1st byte of tag name */
2268 const char *tag_end_p1; /* 1st byte after tag name */
2269 symint_t index; /* index of tag start block */
2270 bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
2274 hash_ptr = hash_string (tag_start,
2275 tag_end_p1 - tag_start,
2279 if (hash_ptr != (shash_t *)0
2280 && hash_ptr->tag_ptr != (tag_t *)0)
2282 tag_ptr = hash_ptr->tag_ptr;
2283 if (index != indexNil)
2285 tag_ptr->basic_type = basic_type;
2286 tag_ptr->ifd = cur_file_ptr->file_index;
2287 tag_ptr->index = index;
2292 (void) add_string (&tag_strings,
2298 tag_ptr = (tag_t *) allocate_word8 ();
2299 tag_ptr->forward_ref = (forward_t *) 0;
2300 tag_ptr->hash_ptr = hash_ptr;
2301 tag_ptr->same_name = hash_ptr->tag_ptr;
2302 tag_ptr->basic_type = basic_type;
2303 tag_ptr->index = index;
2304 tag_ptr->ifd = (index == indexNil) ? -1 : cur_file_ptr->file_index;
2305 tag_ptr->same_block = cur_tag_head->first_tag;
2307 cur_tag_head->first_tag = tag_ptr;
2308 hash_ptr->tag_ptr = tag_ptr;
2314 /* Add an unknown {struct, union, enum} tag. */
2317 add_unknown_tag (ptag)
2318 tag_t *ptag; /* pointer to tag information */
2320 shash_t *hash_ptr = ptag->hash_ptr;
2321 char *name_start = hash_ptr->string;
2322 char *name_end_p1 = name_start + hash_ptr->len;
2323 forward_t *f_next = ptag->forward_ref;
2326 int file_index = cur_file_ptr->file_index;
2330 char *agg_type = "{unknown aggregate type}";
2331 switch (ptag->basic_type)
2333 case bt_Struct: agg_type = "struct"; break;
2334 case bt_Union: agg_type = "union"; break;
2335 case bt_Enum: agg_type = "enum"; break;
2339 fprintf (stderr, "unknown %s %.*s found\n", agg_type,
2340 hash_ptr->len, name_start);
2343 sym_index = add_local_symbol (name_start,
2350 (void) add_local_symbol (name_start,
2357 while (f_next != (forward_t *)0)
2360 f_next = f_next->next;
2362 f_cur->ifd_ptr->isym = file_index;
2363 f_cur->index_ptr->rndx.index = sym_index;
2365 free_word8 ((word8_t *) f_cur);
2372 /* Add a procedure to the current file's list of procedures, and record
2373 this is the current procedure. If the assembler created a PDR for
2374 this procedure, use that to initialize the current PDR. */
2377 add_procedure (func_start, func_end_p1)
2378 const char *func_start; /* 1st byte of func name */
2379 const char *func_end_p1; /* 1st byte after func name */
2381 register PDR *new_proc_ptr;
2382 register efdr_t *file_ptr = cur_file_ptr;
2383 register varray_t *vp = &file_ptr->procs;
2384 register symint_t value = 0;
2385 register st_t proc_type = st_Proc;
2386 register shash_t *shash_ptr = hash_string (func_start,
2387 func_end_p1 - func_start,
2392 fputc ('\n', stderr);
2394 if (vp->objects_last_page == vp->objects_per_page)
2395 add_varray_page (vp);
2397 cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
2399 vp->num_allocated++;
2402 /* Did the assembler create this procedure? If so, get the PDR information. */
2403 cur_oproc_ptr = (PDR *)0;
2404 if (shash_ptr != (shash_t *)0)
2406 register PDR *old_proc_ptr = shash_ptr->proc_ptr;
2407 register SYMR *sym_ptr = shash_ptr->sym_ptr;
2409 if (old_proc_ptr != (PDR *)0
2410 && sym_ptr != (SYMR *)0
2411 && ((st_t)sym_ptr->st == st_Proc || (st_t)sym_ptr->st == st_StaticProc))
2413 cur_oproc_ptr = old_proc_ptr;
2414 value = sym_ptr->value;
2415 proc_type = (st_t)sym_ptr->st;
2416 *new_proc_ptr = *old_proc_ptr; /* initialize */
2420 if (cur_oproc_ptr == (PDR *)0)
2421 error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
2423 /* Determine the start of symbols. */
2424 new_proc_ptr->isym = file_ptr->symbols.num_allocated;
2426 /* Push the start of the function. */
2427 (void) add_local_symbol (func_start,
2436 /* Add a new filename, and set up all of the file relative
2437 virtual arrays (strings, symbols, aux syms, etc.). Record
2438 where the current file structure lives. */
2441 add_file (file_start, file_end_p1)
2442 const char *file_start; /* first byte in string */
2443 const char *file_end_p1; /* first byte after string */
2445 static char zero_bytes[2] = { '\0', '\0' };
2447 register Ptrdiff_t len = file_end_p1 - file_start;
2448 register int first_ch = *file_start;
2449 register efdr_t *file_ptr;
2452 fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
2454 /* See if the file has already been created. */
2455 for (file_ptr = first_file;
2456 file_ptr != (efdr_t *)0;
2457 file_ptr = file_ptr->next_file)
2459 if (first_ch == file_ptr->name[0]
2460 && file_ptr->name[len] == '\0'
2461 && memcmp ((CPTR_T) file_start, (CPTR_T) file_ptr->name, len) == 0)
2463 cur_file_ptr = file_ptr;
2468 /* If this is a new file, create it. */
2469 if (file_ptr == (efdr_t *)0)
2471 if (file_desc.objects_last_page == file_desc.objects_per_page)
2472 add_varray_page (&file_desc);
2474 file_ptr = cur_file_ptr =
2475 &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
2476 *file_ptr = init_file;
2478 file_ptr->file_index = file_desc.num_allocated++;
2480 /* Allocate the string hash table. */
2481 file_ptr->shash_head = (shash_t **) allocate_page ();
2483 /* Make sure 0 byte in string table is null */
2484 add_string (&file_ptr->strings,
2485 &file_ptr->shash_head[0],
2490 if (file_end_p1 - file_start > PAGE_USIZE-2)
2491 fatal ("Filename goes over one page boundary.");
2493 /* Push the start of the filename. We assume that the filename
2494 will be stored at string offset 1. */
2495 (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
2496 (symint_t)0, (symint_t)0);
2497 file_ptr->fdr.rss = 1;
2498 file_ptr->name = &file_ptr->strings.last->datum->byte[1];
2499 file_ptr->name_len = file_end_p1 - file_start;
2501 /* Update the linked list of file descriptors. */
2502 if (first_file == (efdr_t *)0)
2503 first_file = file_ptr;
2505 last_file->next_file = file_ptr;
2507 last_file = file_ptr;
2509 /* Add void & int types to the file (void should be first to catch
2510 errant 0's within the index fields). */
2511 file_ptr->void_type = add_aux_sym_tir (&void_type_info,
2513 &cur_file_ptr->thash_head[0]);
2515 file_ptr->int_type = add_aux_sym_tir (&int_type_info,
2517 &cur_file_ptr->thash_head[0]);
2522 /* Add a stream of random bytes to a varray. */
2525 add_bytes (vp, input_ptr, nitems)
2526 varray_t *vp; /* virtual array to add too */
2527 char *input_ptr; /* start of the bytes */
2528 Size_t nitems; /* # items to move */
2530 register Size_t move_items;
2531 register Size_t move_bytes;
2536 if (vp->objects_last_page >= vp->objects_per_page)
2537 add_varray_page (vp);
2539 ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
2540 move_items = vp->objects_per_page - vp->objects_last_page;
2541 if (move_items > nitems)
2542 move_items = nitems;
2544 move_bytes = move_items * vp->object_size;
2545 nitems -= move_items;
2547 if (move_bytes >= 32)
2549 (void) memcpy ((PTR_T) ptr, (CPTR_T) input_ptr, move_bytes);
2550 input_ptr += move_bytes;
2554 while (move_bytes-- > 0)
2555 *ptr++ = *input_ptr++;
2561 /* Convert storage class to string. */
2564 sc_to_string(storage_class)
2567 switch(storage_class)
2569 case sc_Nil: return "Nil,";
2570 case sc_Text: return "Text,";
2571 case sc_Data: return "Data,";
2572 case sc_Bss: return "Bss,";
2573 case sc_Register: return "Register,";
2574 case sc_Abs: return "Abs,";
2575 case sc_Undefined: return "Undefined,";
2576 case sc_CdbLocal: return "CdbLocal,";
2577 case sc_Bits: return "Bits,";
2578 case sc_CdbSystem: return "CdbSystem,";
2579 case sc_RegImage: return "RegImage,";
2580 case sc_Info: return "Info,";
2581 case sc_UserStruct: return "UserStruct,";
2582 case sc_SData: return "SData,";
2583 case sc_SBss: return "SBss,";
2584 case sc_RData: return "RData,";
2585 case sc_Var: return "Var,";
2586 case sc_Common: return "Common,";
2587 case sc_SCommon: return "SCommon,";
2588 case sc_VarRegister: return "VarRegister,";
2589 case sc_Variant: return "Variant,";
2590 case sc_SUndefined: return "SUndefined,";
2591 case sc_Init: return "Init,";
2592 case sc_Max: return "Max,";
2599 /* Convert symbol type to string. */
2602 st_to_string(symbol_type)
2607 case st_Nil: return "Nil,";
2608 case st_Global: return "Global,";
2609 case st_Static: return "Static,";
2610 case st_Param: return "Param,";
2611 case st_Local: return "Local,";
2612 case st_Label: return "Label,";
2613 case st_Proc: return "Proc,";
2614 case st_Block: return "Block,";
2615 case st_End: return "End,";
2616 case st_Member: return "Member,";
2617 case st_Typedef: return "Typedef,";
2618 case st_File: return "File,";
2619 case st_RegReloc: return "RegReloc,";
2620 case st_Forward: return "Forward,";
2621 case st_StaticProc: return "StaticProc,";
2622 case st_Constant: return "Constant,";
2623 case st_Str: return "String,";
2624 case st_Number: return "Number,";
2625 case st_Expr: return "Expr,";
2626 case st_Type: return "Type,";
2627 case st_Max: return "Max,";
2634 /* Read a line from standard input, and return the start of the
2635 buffer (which is grows if the line is too big). */
2638 read_line __proto((void))
2643 if (cur_line_start == (char *)0)
2644 { /* allocate initial page */
2645 cur_line_start = (char *) allocate_page ();
2646 cur_line_alloc = PAGE_SIZE;
2649 cur_line_nbytes = 0;
2652 for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
2654 if (++cur_line_nbytes >= cur_line_alloc-1)
2656 register int num_pages = cur_line_alloc / PAGE_SIZE;
2657 register char *old_buffer = cur_line_start;
2659 cur_line_alloc += PAGE_SIZE;
2660 cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
2661 memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
2663 ptr = cur_line_start + cur_line_nbytes - 1;
2670 cur_line_ptr = cur_line_start;
2671 return cur_line_ptr;
2676 pfatal_with_name (input_name);
2678 cur_line_ptr = (char *)0;
2683 /* Parse #.begin directives which have a label as the first argument
2684 which gives the location of the start of the block. */
2688 const char *start; /* start of directive */
2690 const char *end_p1; /* end of label */
2692 shash_t *hash_ptr; /* hash pointer to lookup label */
2694 if (cur_file_ptr == (efdr_t *)0)
2696 error ("#.begin directive without a preceeding .file directive");
2700 if (cur_proc_ptr == (PDR *)0)
2702 error ("#.begin directive without a preceeding .ent directive");
2706 for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2709 hash_ptr = hash_string (start,
2714 if (hash_ptr == (shash_t *)0)
2716 error ("Label %.*s not found for #.begin", end_p1 - start, start);
2720 (void) add_local_symbol ((const char *)0,
2724 (symint_t)hash_ptr->sym_ptr->value,
2729 /* Parse #.bend directives which have a label as the first argument
2730 which gives the location of the end of the block. */
2734 const char *start; /* start of directive */
2736 const char *end_p1; /* end of label */
2738 shash_t *hash_ptr; /* hash pointer to lookup label */
2740 if (cur_file_ptr == (efdr_t *)0)
2742 error ("#.begin directive without a preceeding .file directive");
2746 if (cur_proc_ptr == (PDR *)0)
2748 error ("#.begin directive without a preceeding .ent directive");
2752 for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2755 hash_ptr = hash_string (start,
2760 if (hash_ptr == (shash_t *)0)
2762 error ("Label %.*s not found for #.begin", end_p1 - start, start);
2766 (void) add_local_symbol ((const char *)0,
2770 (symint_t)hash_ptr->sym_ptr->value,
2775 /* Parse #.def directives, which are contain standard COFF subdirectives
2776 to describe the debugging format. These subdirectives include:
2778 .scl specify storage class
2779 .val specify a value
2780 .endef specify end of COFF directives
2781 .type specify the type
2782 .size specify the size of an array
2783 .dim specify an array dimension
2784 .tag specify a tag for a struct, union, or enum. */
2787 parse_def (name_start)
2788 const char *name_start; /* start of directive */
2790 const char *dir_start; /* start of current directive*/
2791 const char *dir_end_p1; /* end+1 of current directive*/
2792 const char *arg_start; /* start of current argument */
2793 const char *arg_end_p1; /* end+1 of current argument */
2794 const char *name_end_p1; /* end+1 of label */
2795 const char *tag_start = (const char *)0; /* start of tag name */
2796 const char *tag_end_p1 = (const char *)0; /* end+1 of tag name */
2797 sc_t storage_class = sc_Nil;
2798 st_t symbol_type = st_Nil;
2800 EXTR *eptr = (EXTR *)0; /* ext. sym equivalent to def*/
2801 int is_function = 0; /* != 0 if function */
2803 symint_t index = cur_file_ptr->void_type;
2805 symint_t arg_number;
2806 symint_t temp_array[ N_TQ ];
2811 static int inside_enumeration = 0; /* is this an enumeration? */
2814 /* Initialize the type information. */
2818 /* Search for the end of the name being defined. */
2819 for (name_end_p1 = name_start; (ch = *name_end_p1) != ';'; name_end_p1++)
2821 if (ch == '\0' || isspace (ch))
2823 error_line = __LINE__;
2829 /* Parse the remaining subdirectives now. */
2830 dir_start = name_end_p1+1;
2833 while ((ch = *dir_start) == ' ' || ch == '\t')
2838 error_line = __LINE__;
2844 if (dir_start[1] == 'e'
2845 && memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
2848 /* Pick up the subdirective now */
2849 for (dir_end_p1 = dir_start+1;
2850 (ch = *dir_end_p1) != ' ' && ch != '\t';
2853 if (ch == '\0' || isspace (ch))
2855 error_line = __LINE__;
2861 /* Pick up the subdirective argument now. */
2862 arg_was_number = arg_number = 0;
2863 arg_end_p1 = (const char *)0;
2864 arg_start = dir_end_p1+1;
2866 while (ch == ' ' || ch == '\t')
2869 if (isdigit (ch) || ch == '-' || ch == '+')
2872 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2873 if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
2877 else if (ch == '\0' || isspace (ch))
2879 error_line = __LINE__;
2884 if (!arg_was_number)
2885 for (arg_end_p1 = arg_start+1; (ch = *arg_end_p1) != ';'; arg_end_p1++)
2887 if (ch == '\0' || isspace (ch))
2889 error_line = __LINE__;
2896 /* Classify the directives now. */
2897 len = dir_end_p1 - dir_start;
2898 switch (dir_start[1])
2901 error_line = __LINE__;
2906 if (len == sizeof (".dim")-1
2907 && memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
2910 symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2912 *t_ptr = arg_number;
2913 while (*arg_end_p1 == ',' && arg_was_number)
2915 arg_start = arg_end_p1+1;
2917 while (ch == ' ' || ch == '\t')
2921 if (isdigit (ch) || ch == '-' || ch == '+')
2924 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2925 if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
2928 if (t_ptr == &temp_array[0])
2930 error_line = __LINE__;
2935 *--t_ptr = arg_number;
2939 /* Reverse order of dimensions. */
2940 while (t_ptr <= &temp_array[ N_TQ-1 ])
2942 if (t.num_dims >= N_TQ-1)
2944 error_line = __LINE__;
2949 t.dimensions[ t.num_dims++ ] = *t_ptr++;
2955 error_line = __LINE__;
2962 if (len == sizeof (".scl")-1
2963 && memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
2965 && arg_number < ((symint_t) C_MAX))
2967 /* If the symbol is a static or external, we have
2968 already gotten the appropriate type and class, so
2969 make sure we don't override those values. This is
2970 needed because there are some type and classes that
2971 are not in COFF, such as short data, etc. */
2972 if (symbol_type == st_Nil)
2974 symbol_type = map_coff_sym_type[arg_number];
2975 storage_class = map_coff_storage [arg_number];
2980 else if (len == sizeof (".size")-1
2981 && memcmp (dir_start, ".size", sizeof (".size")-1) == 0
2984 symint_t *t_ptr = &temp_array[ N_TQ-1 ];
2986 *t_ptr = arg_number;
2987 while (*arg_end_p1 == ',' && arg_was_number)
2989 arg_start = arg_end_p1+1;
2991 while (ch == ' ' || ch == '\t')
2995 if (isdigit (ch) || ch == '-' || ch == '+')
2998 arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
2999 if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3002 if (t_ptr == &temp_array[0])
3004 error_line = __LINE__;
3009 *--t_ptr = arg_number;
3013 /* Reverse order of sizes. */
3014 while (t_ptr <= &temp_array[ N_TQ-1 ])
3016 if (t.num_sizes >= N_TQ-1)
3018 error_line = __LINE__;
3023 t.sizes[ t.num_sizes++ ] = *t_ptr++;
3030 error_line = __LINE__;
3037 if (len == sizeof (".type")-1
3038 && memcmp (dir_start, ".type", sizeof (".type")-1) == 0
3041 tq_t *tq_ptr = &t.type_qualifiers[0];
3043 t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
3044 t.basic_type = map_coff_types [(int)t.orig_type];
3045 for (i = N_TQ-1; i >= 0; i--)
3047 int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
3050 if (dt != (int)DT_NON)
3051 *tq_ptr++ = map_coff_derived_type [dt];
3054 /* If this is a function, ignore it, so that we don't get
3055 two entries (one from the .ent, and one for the .def
3056 that preceedes it). Save the type information so that
3057 the end block can properly add it after the begin block
3058 index. For MIPS knows what reason, we must strip off
3059 the function type at this point. */
3060 if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
3063 tq_ptr[-1] = tq_Nil;
3069 else if (len == sizeof (".tag")-1
3070 && memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
3072 tag_start = arg_start;
3073 tag_end_p1 = arg_end_p1;
3079 error_line = __LINE__;
3086 if (len == sizeof (".val")-1
3087 && memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
3092 /* If the value is not an integer value, it must be the
3093 name of a static or global item. Look up the name in
3094 the orignal symbol table to pick up the storage
3095 class, symbol type, etc. */
3098 shash_t *orig_hash_ptr; /* hash within orig sym table*/
3099 shash_t *ext_hash_ptr; /* hash within ext. sym table*/
3101 ext_hash_ptr = hash_string (arg_start,
3102 arg_end_p1 - arg_start,
3106 if (ext_hash_ptr != (shash_t *)0
3107 && ext_hash_ptr->esym_ptr != (EXTR *)0)
3108 eptr = ext_hash_ptr->esym_ptr;
3110 orig_hash_ptr = hash_string (arg_start,
3111 arg_end_p1 - arg_start,
3115 if ((orig_hash_ptr == (shash_t *)0
3116 || orig_hash_ptr->sym_ptr == (SYMR *)0)
3117 && eptr == (EXTR *)0)
3118 error ("internal error, %.*s not found in original or external symbol tables",
3119 arg_end_p1 - arg_start,
3123 SYMR *ptr = (orig_hash_ptr != (shash_t *)0
3124 && orig_hash_ptr->sym_ptr != (SYMR *)0)
3125 ? orig_hash_ptr->sym_ptr
3128 symbol_type = (st_t) ptr->st;
3129 storage_class = (sc_t) ptr->sc;
3137 error_line = __LINE__;
3143 /* Set up to find next directive. */
3144 dir_start = arg_end_p1 + 1;
3148 t.extra_sizes = (tag_start != (char *)0);
3151 int diff = t.num_dims - t.num_sizes;
3152 int i = t.num_dims - 1;
3155 if (t.num_sizes != 1 || diff < 0)
3157 error_line = __LINE__;
3162 /* If this is an array, make sure the same number of dimensions
3163 and sizes were passed, creating extra sizes for multiply
3164 dimensioned arrays if not passed. */
3169 for (j = (sizeof (t.sizes) / sizeof (t.sizes[0])) - 1; j >= 0; j--)
3170 t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
3172 t.num_sizes = i + 1;
3173 for ( i--; i >= 0; i-- )
3174 t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
3178 else if (symbol_type == st_Member && t.num_sizes - t.extra_sizes == 1)
3179 { /* Is this a bitfield? This is indicated by a structure memeber
3180 having a size field that isn't an array. */
3186 /* Except for enumeration members & begin/ending of scopes, put the
3187 type word in the aux. symbol table. */
3189 if (symbol_type == st_Block || symbol_type == st_End)
3192 else if (inside_enumeration)
3193 index = cur_file_ptr->void_type;
3197 if (t.basic_type == bt_Struct
3198 || t.basic_type == bt_Union
3199 || t.basic_type == bt_Enum)
3201 if (tag_start == (char *)0)
3203 error ("No tag specified for %.*s",
3204 name_end_p1 - name_start,
3209 t.tag_ptr = get_tag (tag_start, tag_end_p1, (symint_t)indexNil,
3215 last_func_type_info = t;
3216 last_func_eptr = eptr;
3220 index = add_aux_sym_tir (&t,
3222 &cur_file_ptr->thash_head[0]);
3226 /* If this is an external or static symbol, update the appropriate
3229 if (eptr != (EXTR *)0
3230 && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *)0))
3232 eptr->ifd = cur_file_ptr->file_index;
3233 eptr->asym.index = index;
3237 /* Do any last minute adjustments that are necessary. */
3238 switch (symbol_type)
3244 /* For the beginning of structs, unions, and enumerations, the
3245 size info needs to be passed in the value field. */
3248 if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
3250 error_line = __LINE__;
3258 inside_enumeration = (t.orig_type == T_ENUM);
3262 /* For the end of structs, unions, and enumerations, omit the
3263 name which is always ".eos". This needs to be done last, so
3264 that any error reporting above gives the correct name. */
3267 name_start = name_end_p1 = (const char *)0;
3268 value = inside_enumeration = 0;
3272 /* Members of structures and unions that aren't bitfields, need
3273 to adjust the value from a byte offset to a bit offset.
3274 Members of enumerations do not have the value adjusted, and
3275 can be distinquished by index == indexNil. For enumerations,
3276 update the maximum enumeration value. */
3279 if (!t.bitfield && !inside_enumeration)
3286 /* Add the symbol, except for global symbols outside of functions,
3287 for which the external symbol table is fine enough. */
3289 if (eptr == (EXTR *)0
3290 || eptr->asym.st == (int)st_Nil
3291 || cur_proc_ptr != (PDR *)0)
3293 symint_t isym = add_local_symbol (name_start,
3300 /* deal with struct, union, and enum tags. */
3301 if (symbol_type == st_Block)
3303 /* Create or update the tag information. */
3304 tag_t *tag_ptr = get_tag (name_start,
3309 /* If there are any forward references, fill in the appropriate
3310 file and symbol indexes. */
3312 symint_t file_index = cur_file_ptr->file_index;
3313 forward_t *f_next = tag_ptr->forward_ref;
3316 while (f_next != (forward_t *)0)
3319 f_next = f_next->next;
3321 f_cur->ifd_ptr->isym = file_index;
3322 f_cur->index_ptr->rndx.index = isym;
3324 free_word8 ((word8_t *) f_cur);
3327 tag_ptr->forward_ref = (forward_t *)0;
3334 /* Error return, issue message. */
3337 error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
3339 error ("compiler error, badly formed #.def");
3345 /* Parse .end directives. */
3349 const char *start; /* start of directive */
3351 register const char *start_func, *end_func_p1;
3353 register symint_t value;
3354 register FDR *orig_fdr;
3356 if (cur_file_ptr == (efdr_t *)0)
3358 error (".end directive without a preceeding .file directive");
3362 if (cur_proc_ptr == (PDR *)0)
3364 error (".end directive without a preceeding .ent directive");
3368 /* Get the function name, skipping whitespace. */
3369 for (start_func = start; isspace (*start_func); start_func++)
3373 if (!IS_ASM_IDENT (ch))
3375 error (".end directive has no name");
3379 for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3383 /* Get the value field for creating the end from the original object
3384 file (which we find by locating the procedure start, and using the
3385 pointer to the end+1 block and backing up. The index points to a
3386 two word aux. symbol, whose first word is the index of the end
3387 symbol, and the second word is the type of the function return
3390 orig_fdr = cur_file_ptr->orig_fdr;
3392 if (orig_fdr != (FDR *)0 && cur_oproc_ptr != (PDR *)0)
3394 register SYMR *sym_ptr = ORIG_LSYMS (orig_fdr->isymBase + cur_oproc_ptr->isym);
3396 if ((st_t)sym_ptr->st == st_Proc
3397 || (st_t)sym_ptr->st == st_StaticProc)
3399 AUXU *aptr = ORIG_AUX (orig_fdr->iauxBase + sym_ptr->index);
3400 symint_t end_index = aptr->isym;
3401 value = (ORIG_LSYMS (orig_fdr->isymBase + end_index - 1))->value;
3405 (void) add_local_symbol (start_func,
3412 cur_proc_ptr = cur_oproc_ptr = (PDR *)0;
3416 /* Parse .ent directives. */
3420 const char *start; /* start of directive */
3422 register const char *start_func, *end_func_p1;
3425 if (cur_file_ptr == (efdr_t *)0)
3427 error (".ent directive without a preceeding .file directive");
3431 if (cur_proc_ptr != (PDR *)0)
3433 error ("second .ent directive found before .end directive");
3437 for (start_func = start; isspace (*start_func); start_func++)
3441 if (!IS_ASM_IDENT (ch))
3443 error (".ent directive has no name");
3447 for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3450 (void) add_procedure (start_func, end_func_p1);
3454 /* Parse .file directives. */
3458 const char *start; /* start of directive */
3461 register char *start_name, *end_name_p1;
3463 (void) strtol (start, &p, 0);
3465 || (start_name = strchr (p, '"')) == (char *)0
3466 || (end_name_p1 = strrchr (++start_name, '"')) == (char *)0)
3468 error ("Illegal .file directive");
3472 if (cur_proc_ptr != (PDR *)0)
3474 error ("No way to handle .file within .ent/.end section");
3478 add_file (start_name, end_name_p1);
3482 /* Parse the input file, and write the lines to the output file
3486 parse_input __proto((void))
3490 register thead_t *ptag_head;
3491 register tag_t *ptag;
3492 register tag_t *ptag_next;
3495 fprintf (stderr, "\tinput\n");
3497 /* Add a dummy scope block around the entire compilation unit for
3498 structures defined outside of blocks. */
3499 ptag_head = (thead_t *) allocate_word8 ();
3500 ptag_head->first_tag = 0;
3501 ptag_head->prev = cur_tag_head;
3502 cur_tag_head = ptag_head;
3504 while ((p = read_line ()) != (char *)0)
3506 /* Skip leading blanks */
3507 while (isspace (*p))
3510 /* See if it's a directive we handle. If so, dispatch handler. */
3511 for (i = 0; i < sizeof (pseudo_ops) / sizeof (pseudo_ops[0]); i++)
3512 if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
3513 && isspace (p[pseudo_ops[i].len]))
3515 p += pseudo_ops[i].len; /* skip to first argument */
3516 while (isspace (*p))
3519 (*pseudo_ops[i].func)( p );
3524 /* Process any tags at global level. */
3525 ptag_head = cur_tag_head;
3526 cur_tag_head = ptag_head->prev;
3528 for (ptag = ptag_head->first_tag;
3532 if (ptag->forward_ref != (forward_t *)0)
3533 add_unknown_tag (ptag);
3535 ptag_next = ptag->same_block;
3536 ptag->hash_ptr->tag_ptr = ptag->same_name;
3537 free_word8 ((word8_t *) ptag);
3540 free_word8 ((word8_t *) ptag_head);
3545 /* Update the global headers with the final offsets in preparation
3546 to write out the .T file. */
3549 update_headers __proto((void))
3551 register symint_t i;
3552 register efdr_t *file_ptr;
3554 /* Set up the symbolic header. */
3555 file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3556 symbolic_header.magic = orig_sym_hdr.magic;
3557 symbolic_header.vstamp = orig_sym_hdr.vstamp;
3559 /* Set up global counts. */
3560 symbolic_header.issExtMax = ext_strings.num_allocated;
3561 symbolic_header.idnMax = dense_num.num_allocated;
3562 symbolic_header.ifdMax = file_desc.num_allocated;
3563 symbolic_header.iextMax = ext_symbols.num_allocated;
3564 symbolic_header.ilineMax = orig_sym_hdr.ilineMax;
3565 symbolic_header.ioptMax = orig_sym_hdr.ioptMax;
3566 symbolic_header.cbLine = orig_sym_hdr.cbLine;
3567 symbolic_header.crfd = orig_sym_hdr.crfd;
3570 /* Loop through each file, figuring out how many local syms,
3571 line numbers, etc. there are. Also, put out end symbol
3572 for the filename. */
3574 for (file_ptr = first_file;
3575 file_ptr != (efdr_t *)0;
3576 file_ptr = file_ptr->next_file)
3578 cur_file_ptr = file_ptr;
3579 (void) add_local_symbol ((const char *)0,
3586 file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
3587 file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
3588 symbolic_header.ipdMax += file_ptr->fdr.cpd;
3590 file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
3591 file_ptr->fdr.isymBase = symbolic_header.isymMax;
3592 symbolic_header.isymMax += file_ptr->fdr.csym;
3594 file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
3595 file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
3596 symbolic_header.iauxMax += file_ptr->fdr.caux;
3598 file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
3599 file_ptr->fdr.issBase = symbolic_header.issMax;
3600 symbolic_header.issMax += file_ptr->fdr.cbSs;
3604 i = WORD_ALIGN (symbolic_header.cbLine); /* line numbers */
3607 symbolic_header.cbLineOffset = file_offset;
3611 i = symbolic_header.ioptMax; /* optimization symbols */
3614 symbolic_header.cbOptOffset = file_offset;
3615 file_offset += i * sizeof (OPTR);
3618 i = symbolic_header.idnMax; /* dense numbers */
3621 symbolic_header.cbDnOffset = file_offset;
3622 file_offset += i * sizeof (DNR);
3625 i = symbolic_header.ipdMax; /* procedure tables */
3628 symbolic_header.cbPdOffset = file_offset;
3629 file_offset += i * sizeof (PDR);
3632 i = symbolic_header.isymMax; /* local symbols */
3635 symbolic_header.cbSymOffset = file_offset;
3636 file_offset += i * sizeof (SYMR);
3639 i = symbolic_header.iauxMax; /* aux syms. */
3642 symbolic_header.cbAuxOffset = file_offset;
3643 file_offset += i * sizeof (TIR);
3646 i = WORD_ALIGN (symbolic_header.issMax); /* local strings */
3649 symbolic_header.cbSsOffset = file_offset;
3653 i = WORD_ALIGN (symbolic_header.issExtMax); /* external strings */
3656 symbolic_header.cbSsExtOffset = file_offset;
3660 i = symbolic_header.ifdMax; /* file tables */
3663 symbolic_header.cbFdOffset = file_offset;
3664 file_offset += i * sizeof (FDR);
3667 i = symbolic_header.crfd; /* relative file descriptors */
3670 symbolic_header.cbRfdOffset = file_offset;
3671 file_offset += i * sizeof (symint_t);
3674 i = symbolic_header.iextMax; /* external symbols */
3677 symbolic_header.cbExtOffset = file_offset;
3678 file_offset += i * sizeof (EXTR);
3683 /* Write out a varray at a given location. */
3686 write_varray (vp, offset, str)
3687 varray_t *vp; /* virtual array */
3688 off_t offset; /* offset to write varray to */
3689 const char *str; /* string to print out when tracing */
3691 int num_write, sys_write;
3694 if (vp->num_allocated == 0)
3698 fprintf (stderr, "\twarray\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3699 vp, offset, vp->num_allocated * vp->object_size, str);
3701 if (file_offset != offset
3702 && fseek (object_stream, (long)offset, SEEK_SET) < 0)
3703 pfatal_with_name (object_name);
3705 for (ptr = vp->first; ptr != (vlinks_t *)0; ptr = ptr->next)
3707 num_write = (ptr->next == (vlinks_t *)0)
3708 ? vp->objects_last_page * vp->object_size
3709 : vp->objects_per_page * vp->object_size;
3711 sys_write = fwrite ((PTR_T) ptr->datum, 1, num_write, object_stream);
3713 pfatal_with_name (object_name);
3715 else if (sys_write != num_write)
3716 fatal ("Wrote %d bytes to %s, system returned %d",
3721 file_offset += num_write;
3726 /* Write out the symbol table in the object file. */
3729 write_object __proto((void))
3736 fprintf (stderr, "\n\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3737 (PTR_T *) &symbolic_header, 0, sizeof (symbolic_header),
3740 sys_write = fwrite ((PTR_T) &symbolic_header,
3742 sizeof (symbolic_header),
3746 pfatal_with_name (object_name);
3748 else if (sys_write != sizeof (symbolic_header))
3749 fatal ("Wrote %d bytes to %s, system returned %d",
3750 sizeof (symbolic_header),
3755 file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3757 if (symbolic_header.cbLine > 0) /* line numbers */
3761 if (file_offset != symbolic_header.cbLineOffset
3762 && fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
3763 pfatal_with_name (object_name);
3766 fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3767 (PTR_T *) &orig_linenum, symbolic_header.cbLineOffset,
3768 symbolic_header.cbLine, "Line numbers");
3770 sys_write = fwrite ((PTR_T) orig_linenum,
3772 symbolic_header.cbLine,
3776 pfatal_with_name (object_name);
3778 else if (sys_write != symbolic_header.cbLine)
3779 fatal ("Wrote %d bytes to %s, system returned %d",
3780 symbolic_header.cbLine,
3784 file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
3787 if (symbolic_header.ioptMax > 0) /* optimization symbols */
3790 long num_write = symbolic_header.ioptMax * sizeof (OPTR);
3792 if (file_offset != symbolic_header.cbOptOffset
3793 && fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
3794 pfatal_with_name (object_name);
3797 fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3798 (PTR_T *) &orig_opt_syms, symbolic_header.cbOptOffset,
3799 num_write, "Optimizer symbols");
3801 sys_write = fwrite ((PTR_T) orig_opt_syms,
3807 pfatal_with_name (object_name);
3809 else if (sys_write != num_write)
3810 fatal ("Wrote %d bytes to %s, system returned %d",
3815 file_offset = symbolic_header.cbOptOffset + num_write;
3818 if (symbolic_header.idnMax > 0) /* dense numbers */
3819 write_varray (&dense_num, (off_t)symbolic_header.cbDnOffset, "Dense numbers");
3821 if (symbolic_header.ipdMax > 0) /* procedure tables */
3823 offset = symbolic_header.cbPdOffset;
3824 for (file_ptr = first_file;
3825 file_ptr != (efdr_t *)0;
3826 file_ptr = file_ptr->next_file)
3828 write_varray (&file_ptr->procs, offset, "Procedure tables");
3829 offset = file_offset;
3833 if (symbolic_header.isymMax > 0) /* local symbols */
3835 offset = symbolic_header.cbSymOffset;
3836 for (file_ptr = first_file;
3837 file_ptr != (efdr_t *)0;
3838 file_ptr = file_ptr->next_file)
3840 write_varray (&file_ptr->symbols, offset, "Local symbols");
3841 offset = file_offset;
3845 if (symbolic_header.iauxMax > 0) /* aux symbols */
3847 offset = symbolic_header.cbAuxOffset;
3848 for (file_ptr = first_file;
3849 file_ptr != (efdr_t *)0;
3850 file_ptr = file_ptr->next_file)
3852 write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
3853 offset = file_offset;
3857 if (symbolic_header.issMax > 0) /* local strings */
3859 offset = symbolic_header.cbSsOffset;
3860 for (file_ptr = first_file;
3861 file_ptr != (efdr_t *)0;
3862 file_ptr = file_ptr->next_file)
3864 write_varray (&file_ptr->strings, offset, "Local strings");
3865 offset = file_offset;
3869 if (symbolic_header.issExtMax > 0) /* external strings */
3870 write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
3872 if (symbolic_header.ifdMax > 0) /* file tables */
3874 offset = symbolic_header.cbFdOffset;
3875 if (file_offset != offset
3876 && fseek (object_stream, (long)offset, SEEK_SET) < 0)
3877 pfatal_with_name (object_name);
3879 file_offset = offset;
3880 for (file_ptr = first_file;
3881 file_ptr != (efdr_t *)0;
3882 file_ptr = file_ptr->next_file)
3885 fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3886 (PTR_T *) &file_ptr->fdr, file_offset, sizeof (FDR), "File header");
3888 sys_write = fwrite (&file_ptr->fdr,
3894 pfatal_with_name (object_name);
3896 else if (sys_write != sizeof (FDR))
3897 fatal ("Wrote %d bytes to %s, system returned %d",
3902 file_offset = offset += sizeof (FDR);
3906 if (symbolic_header.crfd > 0) /* relative file descriptors */
3909 symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
3911 if (file_offset != symbolic_header.cbRfdOffset
3912 && fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
3913 pfatal_with_name (object_name);
3916 fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
3917 (PTR_T *) &orig_rfds, symbolic_header.cbRfdOffset,
3918 num_write, "Relative file descriptors");
3920 sys_write = fwrite (orig_rfds,
3926 pfatal_with_name (object_name);
3928 else if (sys_write != num_write)
3929 fatal ("Wrote %d bytes to %s, system returned %d",
3934 file_offset = symbolic_header.cbRfdOffset + num_write;
3937 if (symbolic_header.issExtMax > 0) /* external symbols */
3938 write_varray (&ext_symbols, (off_t)symbolic_header.cbExtOffset, "External symbols");
3940 if (fclose (object_stream) != 0)
3941 pfatal_with_name (object_name);
3945 /* Read some bytes at a specified location, and return a pointer. */
3948 read_seek (size, offset, str)
3949 Size_t size; /* # bytes to read */
3950 off_t offset; /* offset to read at */
3951 const char *str; /* name for tracing */
3956 if (size == 0) /* nothing to read */
3960 fprintf (stderr, "\trseek\tsize = %7u, offset = %7u, currently at %7u, %s\n",
3961 size, offset, file_offset, str);
3963 #ifndef MALLOC_CHECK
3964 ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
3966 ptr = (page_t *) xcalloc (1, size);
3969 /* If we need to seek, and the distance is nearby, just do some reads,
3970 to speed things up. */
3971 if (file_offset != offset)
3973 symint_t difference = offset - file_offset;
3977 char small_buffer[8];
3979 sys_read = fread (small_buffer, 1, difference, obj_in_stream);
3981 pfatal_with_name (obj_in_name);
3983 if (sys_read != difference)
3984 fatal ("Wanted to read %d bytes from %s, system returned %d",
3989 else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
3990 pfatal_with_name (obj_in_name);
3993 sys_read = fread ((PTR_T)ptr, 1, size, obj_in_stream);
3995 pfatal_with_name (obj_in_name);
3997 if (sys_read != size)
3998 fatal ("Wanted to read %d bytes from %s, system returned %d",
4003 file_offset = offset + size;
4005 if (file_offset > max_file_offset)
4006 max_file_offset = file_offset;
4012 /* Read the existing object file (and copy to the output object file
4013 if it is different from the input object file), and remove the old
4017 copy_object __proto((void))
4019 char buffer[ PAGE_SIZE ];
4020 register int sys_read;
4021 register int remaining;
4022 register int num_write;
4023 register int sys_write;
4024 register int fd, es;
4025 register int delete_ifd = 0;
4026 struct stat stat_buf;
4029 fprintf (stderr, "\tcopy\n");
4031 if (fstat (fileno (obj_in_stream), &stat_buf) != 0
4032 || fseek (obj_in_stream, 0L, SEEK_SET) != 0)
4033 pfatal_with_name (obj_in_name);
4035 sys_read = fread ((PTR_T) &orig_file_header,
4037 sizeof (struct filehdr),
4041 pfatal_with_name (obj_in_name);
4043 else if (sys_read == 0 && feof (obj_in_stream))
4044 return; /* create a .T file sans file header */
4046 else if (sys_read < sizeof (struct filehdr))
4047 fatal ("Wanted to read %d bytes from %s, system returned %d",
4048 sizeof (struct filehdr),
4053 if (orig_file_header.f_flags != 0)
4054 fatal ("Non-zero flags encountered in %s filehdr", input_name);
4056 if (orig_file_header.f_nsyms != sizeof (HDRR))
4057 fatal ("%s symbolic header wrong size (%d bytes, should be %d)",
4058 input_name, orig_file_header.f_nsyms, sizeof (HDRR));
4061 /* Read in the current symbolic header. */
4062 if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
4063 pfatal_with_name (input_name);
4065 sys_read = fread ((PTR_T) &orig_sym_hdr,
4067 sizeof (orig_sym_hdr),
4071 pfatal_with_name (object_name);
4073 else if (sys_read < sizeof (struct filehdr))
4074 fatal ("Wanted to read %d bytes from %s, system returned %d",
4075 sizeof (struct filehdr),
4080 /* Read in each of the sections if they exist in the object file.
4081 We read things in in the order the mips assembler creates the
4082 sections, so in theory no extra seeks are done.
4084 For simplicity sake, round each read up to a page boundary,
4085 we may want to revisit this later.... */
4087 file_offset = orig_file_header.f_symptr + sizeof (struct filehdr);
4089 if (orig_sym_hdr.cbLine > 0) /* line numbers */
4090 orig_linenum = (char *) read_seek ((Size_t)orig_sym_hdr.cbLine,
4091 orig_sym_hdr.cbLineOffset,
4094 if (orig_sym_hdr.ipdMax > 0) /* procedure tables */
4095 orig_procs = (PDR *) read_seek ((Size_t)orig_sym_hdr.ipdMax * sizeof (PDR),
4096 orig_sym_hdr.cbPdOffset,
4097 "Procedure tables");
4099 if (orig_sym_hdr.isymMax > 0) /* local symbols */
4100 orig_local_syms = (SYMR *) read_seek ((Size_t)orig_sym_hdr.isymMax * sizeof (SYMR),
4101 orig_sym_hdr.cbSymOffset,
4104 if (orig_sym_hdr.iauxMax > 0) /* aux symbols */
4105 orig_aux_syms = (AUXU *) read_seek ((Size_t)orig_sym_hdr.iauxMax * sizeof (AUXU),
4106 orig_sym_hdr.cbAuxOffset,
4109 if (orig_sym_hdr.issMax > 0) /* local strings */
4110 orig_local_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issMax,
4111 orig_sym_hdr.cbSsOffset,
4114 if (orig_sym_hdr.issExtMax > 0) /* external strings */
4115 orig_ext_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issExtMax,
4116 orig_sym_hdr.cbSsExtOffset,
4117 "External strings");
4119 if (orig_sym_hdr.ifdMax > 0) /* file tables */
4120 orig_files = (FDR *) read_seek ((Size_t)orig_sym_hdr.ifdMax * sizeof (FDR),
4121 orig_sym_hdr.cbFdOffset,
4124 if (orig_sym_hdr.crfd > 0) /* relative file descriptors */
4125 orig_rfds = (symint_t *) read_seek ((Size_t)orig_sym_hdr.crfd * sizeof (symint_t),
4126 orig_sym_hdr.cbRfdOffset,
4127 "Relative file descriptors");
4129 if (orig_sym_hdr.issExtMax > 0) /* external symbols */
4130 orig_ext_syms = (EXTR *) read_seek ((Size_t)orig_sym_hdr.iextMax * sizeof (EXTR),
4131 orig_sym_hdr.cbExtOffset,
4132 "External symbols");
4134 if (orig_sym_hdr.idnMax > 0) /* dense numbers */
4136 orig_dense = (DNR *) read_seek ((Size_t)orig_sym_hdr.idnMax * sizeof (DNR),
4137 orig_sym_hdr.cbDnOffset,
4140 add_bytes (&dense_num, (char *) orig_dense, (Size_t)orig_sym_hdr.idnMax);
4143 if (orig_sym_hdr.ioptMax > 0) /* opt symbols */
4144 orig_opt_syms = (OPTR *) read_seek ((Size_t)orig_sym_hdr.ioptMax * sizeof (OPTR),
4145 orig_sym_hdr.cbOptOffset,
4146 "Optimizer symbols");
4150 /* Abort if the symbol table is not last. */
4151 if (max_file_offset != stat_buf.st_size)
4152 fatal ("Symbol table is not last (symbol table ends at %ld, .o ends at %ld",
4157 /* If the first original file descriptor is a dummy which the assembler
4158 put out, but there are no symbols in it, skip it now. */
4159 if (orig_sym_hdr.ifdMax > 1
4160 && orig_files->csym == 2
4161 && orig_files->caux == 0)
4163 char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
4164 char *suffix = strrchr (filename, '.');
4166 if (suffix != (char *)0 && strcmp (suffix, ".s") == 0)
4171 /* Loop, adding each of the external symbols. These must be in
4172 order or otherwise we would have to change the relocation
4173 entries. We don't just call add_bytes, because we need to have
4174 the names put into the external hash table. We set the type to
4175 'void' for now, and parse_def will fill in the correct type if it
4176 is in the symbol table. */
4179 fprintf (stderr, "\tehash\n");
4181 for (es = 0; es < orig_sym_hdr.iextMax; es++)
4183 register EXTR *eptr = orig_ext_syms + es;
4184 register char *ename = ORIG_ESTRS (eptr->asym.iss);
4186 (void) add_ext_symbol (ename,
4187 ename + strlen (ename),
4188 (st_t) eptr->asym.st,
4189 (sc_t) eptr->asym.sc,
4191 (symint_t)((eptr->asym.index == indexNil) ? indexNil : 0),
4192 eptr->ifd - delete_ifd);
4196 /* For each of the files in the object file, copy the symbols, and such
4197 into the varrays for the new object file. */
4199 for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4201 register FDR *fd_ptr = ORIG_FILES (fd);
4202 register char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4203 register SYMR *sym_start;
4205 register SYMR *sym_end_p1;
4206 register PDR *proc_start;
4208 register PDR *proc_end_p1;
4210 /* file support itself. */
4211 add_file (filename, filename + strlen (filename));
4212 cur_file_ptr->orig_fdr = fd_ptr;
4214 /* Copy stuff that's just passed through (such as line #'s) */
4215 cur_file_ptr->fdr.adr = fd_ptr->adr;
4216 cur_file_ptr->fdr.ilineBase = fd_ptr->ilineBase;
4217 cur_file_ptr->fdr.cline = fd_ptr->cline;
4218 cur_file_ptr->fdr.rfdBase = fd_ptr->rfdBase;
4219 cur_file_ptr->fdr.crfd = fd_ptr->crfd;
4220 cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
4221 cur_file_ptr->fdr.cbLine = fd_ptr->cbLine;
4222 cur_file_ptr->fdr.fMerge = fd_ptr->fMerge;
4223 cur_file_ptr->fdr.fReadin = fd_ptr->fReadin;
4224 cur_file_ptr->fdr.glevel = fd_ptr->glevel;
4227 fprintf (stderr, "\thash\tstart, filename %s\n", filename);
4229 /* For each of the static and global symbols defined, add them
4230 to the hash table of original symbols, so we can look up
4233 sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4234 sym_end_p1 = sym_start + fd_ptr->csym;
4235 for (sym = sym_start; sym < sym_end_p1; sym++)
4237 switch ((st_t) sym->st)
4248 auto symint_t hash_index;
4249 register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4250 register Size_t len = strlen (str);
4251 register shash_t *shash_ptr = hash_string (str,
4256 if (shash_ptr != (shash_t *)0)
4257 error ("internal error, %s is already in original symbol table", str);
4261 shash_ptr = (shash_t *) allocate_word8 ();
4262 shash_ptr->next = orig_str_hash[hash_index];
4263 orig_str_hash[hash_index] = shash_ptr;
4265 shash_ptr->len = len;
4266 shash_ptr->index = indexNil;
4267 shash_ptr->string = str;
4268 shash_ptr->sym_ptr = sym;
4276 fprintf (stderr, "\thash\tdone, filename %s\n", filename);
4277 fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
4280 /* Go through each of the procedures in this file, and add the
4281 procedure pointer to the hash entry for the given name. */
4283 proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
4284 proc_end_p1 = proc_start + fd_ptr->cpd;
4285 for (proc = proc_start; proc < proc_end_p1; proc++)
4287 register SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
4288 register char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
4289 register Size_t len = strlen (str);
4290 register shash_t *shash_ptr = hash_string (str,
4295 if (shash_ptr == (shash_t *)0)
4296 error ("internal error, function %s is not in original symbol table", str);
4299 shash_ptr->proc_ptr = proc;
4303 fprintf (stderr, "\tproc\tdone, filename %s\n", filename);
4306 cur_file_ptr = first_file;
4309 /* Copy all of the object file up to the symbol table. Originally
4310 we were going to use ftruncate, but that doesn't seem to work
4311 on Ultrix 3.1.... */
4313 if (fseek (obj_in_stream, (long)0, SEEK_SET) != 0)
4314 pfatal_with_name (obj_in_name);
4316 if (fseek (object_stream, (long)0, SEEK_SET) != 0)
4317 pfatal_with_name (object_name);
4319 for (remaining = orig_file_header.f_symptr;
4321 remaining -= num_write)
4323 num_write = (remaining <= sizeof (buffer)) ? remaining : sizeof (buffer);
4324 sys_read = fread ((PTR_T) buffer, 1, num_write, obj_in_stream);
4326 pfatal_with_name (obj_in_name);
4328 else if (sys_read != num_write)
4329 fatal ("Wanted to read %d bytes from %s, system returned %d",
4334 sys_write = fwrite (buffer, 1, num_write, object_stream);
4336 pfatal_with_name (object_name);
4338 else if (sys_write != num_write)
4339 fatal ("Wrote %d bytes to %s, system returned %d",
4347 /* Ye olde main program. */
4355 char *p = strrchr (argv[0], '/');
4359 progname = (p != 0) ? p+1 : argv[0];
4361 (void) signal (SIGSEGV, catch_signal);
4362 (void) signal (SIGBUS, catch_signal);
4363 (void) signal (SIGABRT, catch_signal);
4365 #if !defined(__SABER__) && !defined(lint)
4366 if (sizeof (efdr_t) > PAGE_USIZE)
4367 fatal ("Efdr_t has a sizeof %d bytes, when it should be less than %d",
4371 if (sizeof (page_t) != PAGE_USIZE)
4372 fatal ("Page_t has a sizeof %d bytes, when it should be %d",
4376 if (sizeof (word8_t) != 8 * sizeof (symint_t))
4377 fatal ("Word8_t has a sizeof %d bytes, when it should be %d",
4379 8 * sizeof (symint_t));
4382 int_type_info = type_info_init;
4383 int_type_info.basic_type = bt_Int;
4385 void_type_info = type_info_init;
4386 void_type_info.basic_type = bt_Void;
4388 while ((option = getopt (argc, argv, "d:i:I:o:v")) != EOF)
4396 debug = strtol (optarg, &num_end, 0);
4397 if ((unsigned)debug > 4 || num_end == optarg)
4403 if (rename_output || obj_in_name != (char *)0)
4408 /* fall through to 'i' case. */
4411 if (obj_in_name == (char *)0)
4413 obj_in_name = optarg;
4421 if (object_name == (char *)0)
4422 object_name = optarg;
4432 if (obj_in_name == (char *)0 && optind <= argc - 2)
4433 obj_in_name = argv[--argc];
4435 if (object_name == (char *)0 && optind <= argc - 2)
4436 object_name = argv[--argc];
4438 /* If there is an output name, but no input name use
4439 the same file for both, deleting the name between
4440 opening it for input and opening it for output. */
4441 if (obj_in_name == (char *)0 && object_name != (char *)0)
4443 obj_in_name = object_name;
4447 if (object_name == (char *)0 || had_errors || optind != argc - 1)
4449 fprintf (stderr, "Calling Sequence:\n");
4450 fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4451 fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4452 fprintf (stderr, "\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n");
4453 fprintf (stderr, "\n");
4454 fprintf (stderr, "Debug levels are:\n");
4455 fprintf (stderr, " 1\tGeneral debug + trace functions/blocks.\n");
4456 fprintf (stderr, " 2\tDebug level 1 + trace externals.\n");
4457 fprintf (stderr, " 3\tDebug level 2 + trace all symbols.\n");
4458 fprintf (stderr, " 4\tDebug level 3 + trace memory allocations.\n");
4465 extern char *version_string;
4466 fprintf (stderr, "mips-tfile version %s", version_string);
4467 #ifdef TARGET_VERSION
4470 fputc ('\n', stderr);
4473 if (obj_in_name == (char *)0)
4474 obj_in_name = object_name;
4476 if (rename_output && rename (object_name, obj_in_name) != 0)
4478 char *buffer = (char *) allocate_multiple_pages (4);
4484 /* Rename failed, copy input file */
4485 in_fd = open (object_name, O_RDONLY, 0666);
4487 pfatal_with_name (object_name);
4489 out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
4491 pfatal_with_name (obj_in_name);
4493 while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
4495 len2 = write (out_fd, buffer, len);
4497 pfatal_with_name (object_name);
4500 fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
4503 free_multiple_pages (buffer, 4);
4506 pfatal_with_name (object_name);
4508 if (close (in_fd) < 0)
4509 pfatal_with_name (object_name);
4511 if (close (out_fd) < 0)
4512 pfatal_with_name (obj_in_name);
4515 /* Must open input before output, since the output may be the same file, and
4516 we need to get the input handle before truncating it. */
4517 obj_in_stream = fopen (obj_in_name, "r");
4518 if (obj_in_stream == (FILE *)0)
4519 pfatal_with_name (obj_in_name);
4521 if (delete_input && unlink (obj_in_name) != 0)
4522 pfatal_with_name (obj_in_name);
4524 object_stream = fopen (object_name, "w");
4525 if (object_stream == (FILE *)0)
4526 pfatal_with_name (object_name);
4528 if (strcmp (argv[optind], "-") != 0)
4530 input_name = argv[optind];
4531 if (freopen (argv[optind], "r", stdin) != stdin)
4532 pfatal_with_name (argv[optind]);
4537 /* Try to prevent stdio from malloc'ing memory for the buffers. At the
4538 same time, increase the size of mips' stdio buffers. */
4540 setvbuf (object_stream, (char *) allocate_multiple_pages (2), _IOFBF, 2*PAGE_SIZE);
4541 setvbuf (obj_in_stream, (char *) allocate_multiple_pages (2), _IOFBF, 2*PAGE_SIZE);
4542 setvbuf (stdin, (char *) allocate_multiple_pages (2), _IOFBF, 2*PAGE_SIZE);
4543 setvbuf (stdout, (char *) allocate_multiple_pages (2), _IOFBF, 2*PAGE_SIZE);
4544 setvbuf (stderr, (char *) allocate_multiple_pages (2), _IOLBF, 2*PAGE_SIZE);
4547 copy_object (); /* scan & copy object file */
4548 parse_input (); /* scan all of input */
4550 update_headers (); /* write out tfile */
4553 return (had_errors) ? 1 : 0;
4557 /* Catch a signal and exit without dumping core. */
4560 catch_signal (signum)
4563 extern char *sys_siglist[NSIG + 1];
4565 (void) signal (signum, SIG_DFL); /* just in case... */
4566 fatal (sys_siglist[signum]);
4569 /* Print a fatal error message. NAME is the text.
4570 Also include a system error message based on `errno'. */
4573 pfatal_with_name (msg)
4576 int save_errno = errno; /* just in case.... */
4577 if (line_number > 0)
4578 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
4580 fprintf (stderr, "%s:", progname);
4584 fprintf (stderr, "[errno = 0] %s\n", msg);
4592 /* Procedure to abort with an out of bounds error message. It has
4593 type int, so it can be used with an ?: expression within the
4594 ORIG_xxx macros, but the function never returns. */
4597 out_of_bounds (index, max, str, prog_line)
4598 symint_t index; /* index that is out of bounds */
4599 symint_t max; /* maximum index */
4600 const char *str; /* string to print out */
4601 int prog_line; /* line number within mips-tfile.c */
4603 if (index < max) /* just in case */
4606 fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n",
4607 progname, input_name, line_number, index, str, max, prog_line);
4610 return 0; /* turn off warning messages */
4614 /* Allocate a cluster of pages. USE_MALLOC says that malloc does not
4615 like sbrk's behind it's back (or sbrk isn't available). If we use
4616 sbrk, we assume it gives us zeroed pages. */
4618 #ifndef MALLOC_CHECK
4622 allocate_cluster (npages)
4625 register page_t *value = (page_t *) calloc (npages, PAGE_USIZE);
4628 fatal ("Virtual memory exhausted.");
4631 fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
4636 #else /* USE_MALLOC */
4639 allocate_cluster (npages)
4642 register page_t *ptr = (page_t *) sbrk (0); /* current sbreak */
4643 unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
4645 if (offset != 0) /* align to a page boundary */
4647 if (sbrk (PAGE_USIZE - offset) == (char *)-1)
4648 pfatal_with_name ("allocate_cluster");
4650 ptr = (page_t *) (((char *)ptr) + PAGE_SIZE - offset);
4653 if (sbrk (npages * PAGE_USIZE) == (char *)-1)
4654 pfatal_with_name ("allocate_cluster");
4657 fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, ptr);
4662 #endif /* USE_MALLOC */
4665 static page_t *cluster_ptr = NULL;
4666 static unsigned pages_left = 0;
4668 #endif /* MALLOC_CHECK */
4671 /* Allocate some pages (which is initialized to 0). */
4674 allocate_multiple_pages (npages)
4677 #ifndef MALLOC_CHECK
4678 if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
4680 pages_left = MAX_CLUSTER_PAGES;
4681 cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
4684 if (npages <= pages_left)
4686 page_t *ptr = cluster_ptr;
4687 cluster_ptr += npages;
4688 pages_left -= npages;
4692 return allocate_cluster (npages);
4694 #else /* MALLOC_CHECK */
4695 return (page_t *) xcalloc (npages, PAGE_SIZE);
4697 #endif /* MALLOC_CHECK */
4701 /* Release some pages. */
4704 free_multiple_pages (page_ptr, npages)
4708 #ifndef MALLOC_CHECK
4709 if (pages_left == 0)
4711 cluster_ptr = page_ptr;
4712 pages_left = npages;
4715 else if ((page_ptr + npages) == cluster_ptr)
4717 cluster_ptr -= npages;
4718 pages_left += npages;
4721 /* otherwise the page is not freed. If more than call is
4722 done, we probably should worry about it, but at present,
4723 the free pages is done right after an allocate. */
4725 #else /* MALLOC_CHECK */
4726 free ((char *) page_ptr);
4728 #endif /* MALLOC_CHECK */
4732 /* Allocate one page (which is initialized to 0). */
4735 allocate_page __proto((void))
4737 #ifndef MALLOC_CHECK
4738 if (pages_left == 0)
4740 pages_left = MAX_CLUSTER_PAGES;
4741 cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
4745 return cluster_ptr++;
4747 #else /* MALLOC_CHECK */
4748 return (page_t *) xcalloc (1, PAGE_SIZE);
4750 #endif /* MALLOC_CHECK */
4754 /* Allocate and release 4 word quanities. */
4756 #ifndef MALLOC_CHECK
4757 static word8_t *word8_free_list = (word8_t *)0;
4761 allocate_word8 __proto((void))
4763 #ifndef MALLOC_CHECK
4764 register word8_t *ptr = word8_free_list;
4765 if (ptr != (word8_t *)0)
4766 word8_free_list = ptr->prev;
4770 register page_t *page_ptr;
4772 page_ptr = allocate_page ();
4773 ptr = &page_ptr->word8[0];
4774 for (i = 0; i < (PAGE_SIZE / sizeof (word8_t)) - 1; i++)
4776 ptr->prev = word8_free_list;
4777 word8_free_list = ptr;
4792 #else /* MALLOC_CHECK */
4793 return (word8_t *) xcalloc (1, sizeof (word8_t));
4795 #endif /* MALLOC_CHECK */
4802 #ifndef MALLOC_CHECK
4803 ptr->prev = word8_free_list;
4804 word8_free_list = ptr;
4806 #else /* MALLOC_CHECK */
4809 #endif /* MALLOC_CHECK */
4812 #endif /* MIPS_DEBUGGING defined */
4815 /* Output an error message and exit */
4825 if (line_number > 0)
4826 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
4828 fprintf (stderr, "%s:", progname);
4831 format = va_arg (ap, char *);
4832 vfprintf (stderr, format, ap);
4834 fprintf (stderr, "\n");
4835 if (line_number > 0)
4836 fprintf (stderr, "line:\t%s\n", cur_line_start);
4850 if (line_number > 0)
4851 fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
4853 fprintf (stderr, "%s:", progname);
4856 format = va_arg (ap, char *);
4857 vfprintf (stderr, format, ap);
4858 fprintf (stderr, "\n");
4859 if (line_number > 0)
4860 fprintf (stderr, "line:\t%s\n", cur_line_start);
4868 /* More 'friendly' abort that prints the line and file.
4869 config.h can #define abort fancy_abort if you like that sort of thing. */
4874 fatal ("Internal abort.");
4878 /* When `malloc.c' is compiled with `rcheck' defined,
4879 it calls this function to report clobberage. */
4888 /* Same as `malloc' but report error if no memory available. */
4894 register PTR_T value = malloc (size);
4896 fatal ("Virtual memory exhausted.");
4899 fprintf (stderr, "\tmalloc\tptr = 0x%.8x, size = %10u\n", value, size);
4904 /* Same as `calloc' but report error if no memory available. */
4907 xcalloc (size1, size2)
4908 Size_t size1, size2;
4910 register PTR_T value = calloc (size1, size2);
4912 fatal ("Virtual memory exhausted.");
4915 fprintf (stderr, "\tcalloc\tptr = 0x%.8x, size1 = %10u, size2 = %10u [%u]\n",
4916 value, size1, size2, size1+size2);
4921 /* Same as `realloc' but report error if no memory available. */
4924 xrealloc (ptr, size)
4928 register PTR_T result = realloc (ptr, size);
4930 fatal ("Virtual memory exhausted.");
4933 fprintf (stderr, "\trealloc\tptr = 0x%.8x, size = %10u, orig = 0x%.8x\n",
4944 fprintf (stderr, "\tfree\tptr = 0x%.8x\n", ptr);