|
|
1.1 root 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).
1.1.1.8 ! root 5: Copyright (C) 1991, 1993, 1994. 1995 Free Software Foundation, Inc.
1.1.1.7 root 6: Contributed by Michael Meissner, [email protected]
7:
1.1 root 8: This file is part of GNU CC.
9:
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)
13: any later version.
14:
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.
19:
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
1.1.1.8 ! root 22: the Free Software Foundation, 59 Temple Place - Suite 330,
! 23: Boston, MA 02111-1307, USA. */
1.1 root 24:
25:
26: /* Here is a brief description of the MIPS ECOFF symbol table. The
27: MIPS symbol table has the following pieces:
28:
29: Symbolic Header
30: |
31: +-- Auxiliary Symbols
32: |
33: +-- Dense number table
34: |
35: +-- Optimizer Symbols
36: |
37: +-- External Strings
38: |
39: +-- External Symbols
40: |
41: +-- Relative file descriptors
42: |
43: +-- File table
44: |
45: +-- Procedure table
46: |
47: +-- Line number table
48: |
49: +-- Local Strings
50: |
51: +-- Local Symbols
52:
53: The symbolic header points to each of the other tables, and also
54: contains the number of entries. It also contains a magic number
55: and MIPS compiler version number, such as 2.0.
56:
57: The auxiliary table is a series of 32 bit integers, that are
58: referenced as needed from the local symbol table. Unlike standard
59: COFF, the aux. information does not follow the symbol that uses
60: it, but rather is a separate table. In theory, this would allow
61: the MIPS compilers to collapse duplicate aux. entries, but I've not
62: noticed this happening with the 1.31 compiler suite. The different
63: types of aux. entries are:
64:
65: 1) dnLow: Low bound on array dimension.
66:
67: 2) dnHigh: High bound on array dimension.
68:
69: 3) isym: Index to the local symbol which is the start of the
70: function for the end of function first aux. entry.
71:
72: 4) width: Width of structures and bitfields.
73:
74: 5) count: Count of ranges for variant part.
75:
76: 6) rndx: A relative index into the symbol table. The relative
77: index field has two parts: rfd which is a pointer into the
78: relative file index table or ST_RFDESCAPE which says the next
79: aux. entry is the file number, and index: which is the pointer
80: into the local symbol within a given file table. This is for
81: things like references to types defined in another file.
82:
83: 7) Type information: This is like the COFF type bits, except it
84: is 32 bits instead of 16; they still have room to add new
85: basic types; and they can handle more than 6 levels of array,
86: pointer, function, etc. Each type information field contains
87: the following structure members:
88:
89: a) fBitfield: a bit that says this is a bitfield, and the
90: size in bits follows as the next aux. entry.
91:
92: b) continued: a bit that says the next aux. entry is a
93: continuation of the current type information (in case
94: there are more than 6 levels of array/ptr/function).
95:
96: c) bt: an integer containing the base type before adding
97: array, pointer, function, etc. qualifiers. The
98: current base types that I have documentation for are:
99:
100: btNil -- undefined
101: btAdr -- address - integer same size as ptr
102: btChar -- character
103: btUChar -- unsigned character
104: btShort -- short
105: btUShort -- unsigned short
106: btInt -- int
107: btUInt -- unsigned int
108: btLong -- long
109: btULong -- unsigned long
110: btFloat -- float (real)
111: btDouble -- Double (real)
112: btStruct -- Structure (Record)
113: btUnion -- Union (variant)
114: btEnum -- Enumerated
115: btTypedef -- defined via a typedef isymRef
116: btRange -- subrange of int
117: btSet -- pascal sets
118: btComplex -- fortran complex
119: btDComplex -- fortran double complex
120: btIndirect -- forward or unnamed typedef
121: btFixedDec -- Fixed Decimal
122: btFloatDec -- Float Decimal
123: btString -- Varying Length Character String
124: btBit -- Aligned Bit String
125: btPicture -- Picture
126: btVoid -- Void (MIPS cc revision >= 2.00)
127:
128: d) tq0 - tq5: type qualifier fields as needed. The
129: current type qualifier fields I have documentation for
130: are:
131:
132: tqNil -- no more qualifiers
133: tqPtr -- pointer
134: tqProc -- procedure
135: tqArray -- array
136: tqFar -- 8086 far pointers
137: tqVol -- volatile
138:
139:
140: The dense number table is used in the front ends, and disappears by
141: the time the .o is created.
142:
143: With the 1.31 compiler suite, the optimization symbols don't seem
144: to be used as far as I can tell.
145:
146: The linker is the first entity that creates the relative file
147: descriptor table, and I believe it is used so that the individual
148: file table pointers don't have to be rewritten when the objects are
149: merged together into the program file.
150:
151: Unlike COFF, the basic symbol & string tables are split into
152: external and local symbols/strings. The relocation information
153: only goes off of the external symbol table, and the debug
154: information only goes off of the internal symbol table. The
155: external symbols can have links to an appropriate file index and
156: symbol within the file to give it the appropriate type information.
157: Because of this, the external symbols are actually larger than the
158: internal symbols (to contain the link information), and contain the
159: local symbol structure as a member, though this member is not the
160: first member of the external symbol structure (!). I suspect this
161: split is to make strip easier to deal with.
162:
163: Each file table has offsets for where the line numbers, local
164: strings, local symbols, and procedure table starts from within the
165: global tables, and the indexs are reset to 0 for each of those
166: tables for the file.
167:
168: The procedure table contains the binary equivalents of the .ent
169: (start of the function address), .frame (what register is the
170: virtual frame pointer, constant offset from the register to obtain
171: the VFP, and what register holds the return address), .mask/.fmask
172: (bitmask of saved registers, and where the first register is stored
173: relative to the VFP) assembler directives. It also contains the
174: low and high bounds of the line numbers if debugging is turned on.
175:
176: The line number table is a compressed form of the normal COFF line
177: table. Each line number entry is either 1 or 3 bytes long, and
178: contains a signed delta from the previous line, and an unsigned
179: count of the number of instructions this statement takes.
180:
181: The local symbol table contains the following fields:
182:
183: 1) iss: index to the local string table giving the name of the
184: symbol.
185:
186: 2) value: value of the symbol (address, register number, etc.).
187:
188: 3) st: symbol type. The current symbol types are:
189:
190: stNil -- Nuthin' special
191: stGlobal -- external symbol
192: stStatic -- static
193: stParam -- procedure argument
194: stLocal -- local variable
195: stLabel -- label
196: stProc -- External Procedure
1.1.1.3 root 197: stBlock -- beginning of block
1.1 root 198: stEnd -- end (of anything)
199: stMember -- member (of anything)
200: stTypedef -- type definition
201: stFile -- file name
202: stRegReloc -- register relocation
203: stForward -- forwarding address
204: stStaticProc -- Static procedure
205: stConstant -- const
206:
207: 4) sc: storage class. The current storage classes are:
208:
209: scText -- text symbol
210: scData -- initialized data symbol
211: scBss -- un-initialized data symbol
212: scRegister -- value of symbol is register number
213: scAbs -- value of symbol is absolute
214: scUndefined -- who knows?
215: scCdbLocal -- variable's value is IN se->va.??
216: scBits -- this is a bit field
217: scCdbSystem -- value is IN debugger's address space
218: scRegImage -- register value saved on stack
219: scInfo -- symbol contains debugger information
220: scUserStruct -- addr in struct user for current process
221: scSData -- load time only small data
222: scSBss -- load time only small common
223: scRData -- load time only read only data
224: scVar -- Var parameter (fortranpascal)
225: scCommon -- common variable
226: scSCommon -- small common
227: scVarRegister -- Var parameter in a register
228: scVariant -- Variant record
229: scSUndefined -- small undefined(external) data
230: scInit -- .init section symbol
231:
232: 5) index: pointer to a local symbol or aux. entry.
233:
234:
235:
236: For the following program:
237:
238: #include <stdio.h>
239:
240: main(){
241: printf("Hello World!\n");
242: return 0;
243: }
244:
245: Mips-tdump produces the following information:
246:
247: Global file header:
248: magic number 0x162
249: # sections 2
250: timestamp 645311799, Wed Jun 13 17:16:39 1990
251: symbolic header offset 284
252: symbolic header size 96
253: optional header 56
254: flags 0x0
255:
256: Symbolic header, magic number = 0x7009, vstamp = 1.31:
257:
258: Info Offset Number Bytes
259: ==== ====== ====== =====
260:
261: Line numbers 380 4 4 [13]
262: Dense numbers 0 0 0
263: Procedures Tables 384 1 52
264: Local Symbols 436 16 192
265: Optimization Symbols 0 0 0
1.1.1.3 root 266: Auxiliary Symbols 628 39 156
1.1 root 267: Local Strings 784 80 80
268: External Strings 864 144 144
269: File Tables 1008 2 144
270: Relative Files 0 0 0
271: External Symbols 1152 20 320
272:
273: File #0, "hello2.c"
274:
275: Name index = 1 Readin = No
276: Merge = No Endian = LITTLE
277: Debug level = G2 Language = C
278: Adr = 0x00000000
279:
280: Info Start Number Size Offset
281: ==== ===== ====== ==== ======
282: Local strings 0 15 15 784
283: Local symbols 0 6 72 436
284: Line numbers 0 13 13 380
285: Optimization symbols 0 0 0 0
286: Procedures 0 1 52 384
287: Auxiliary symbols 0 14 56 628
288: Relative Files 0 0 0 0
289:
290: There are 6 local symbols, starting at 436
291:
292: Symbol# 0: "hello2.c"
293: End+1 symbol = 6
294: String index = 1
295: Storage class = Text Index = 6
296: Symbol type = File Value = 0
297:
298: Symbol# 1: "main"
299: End+1 symbol = 5
300: Type = int
301: String index = 10
302: Storage class = Text Index = 12
303: Symbol type = Proc Value = 0
304:
305: Symbol# 2: ""
306: End+1 symbol = 4
307: String index = 0
308: Storage class = Text Index = 4
309: Symbol type = Block Value = 8
310:
311: Symbol# 3: ""
312: First symbol = 2
313: String index = 0
314: Storage class = Text Index = 2
315: Symbol type = End Value = 28
316:
317: Symbol# 4: "main"
318: First symbol = 1
319: String index = 10
320: Storage class = Text Index = 1
321: Symbol type = End Value = 52
322:
323: Symbol# 5: "hello2.c"
324: First symbol = 0
325: String index = 1
326: Storage class = Text Index = 0
327: Symbol type = End Value = 0
328:
329: There are 14 auxiliary table entries, starting at 628.
330:
331: * #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
332: * #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
333: * #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0]
334: * #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0]
335: * #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
336: * #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0]
337: * #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0]
338: * #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0]
339: * #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0]
340: * #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0]
341: * #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0]
342: * #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0]
343: #12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0]
344: #13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
345:
346: There are 1 procedure descriptor entries, starting at 0.
347:
348: Procedure descriptor 0:
349: Name index = 10 Name = "main"
350: .mask 0x80000000,-4 .fmask 0x00000000,0
351: .frame $29,24,$31
352: Opt. start = -1 Symbols start = 1
353: First line # = 3 Last line # = 6
354: Line Offset = 0 Address = 0x00000000
355:
356: There are 4 bytes holding line numbers, starting at 380.
357: Line 3, delta 0, count 2
358: Line 4, delta 1, count 3
359: Line 5, delta 1, count 2
360: Line 6, delta 1, count 6
361:
362: File #1, "/usr/include/stdio.h"
363:
364: Name index = 1 Readin = No
365: Merge = Yes Endian = LITTLE
366: Debug level = G2 Language = C
367: Adr = 0x00000000
368:
369: Info Start Number Size Offset
370: ==== ===== ====== ==== ======
371: Local strings 15 65 65 799
372: Local symbols 6 10 120 508
373: Line numbers 0 0 0 380
374: Optimization symbols 0 0 0 0
375: Procedures 1 0 0 436
376: Auxiliary symbols 14 25 100 684
377: Relative Files 0 0 0 0
378:
379: There are 10 local symbols, starting at 442
380:
381: Symbol# 0: "/usr/include/stdio.h"
382: End+1 symbol = 10
383: String index = 1
384: Storage class = Text Index = 10
385: Symbol type = File Value = 0
386:
387: Symbol# 1: "_iobuf"
388: End+1 symbol = 9
389: String index = 22
390: Storage class = Info Index = 9
391: Symbol type = Block Value = 20
392:
393: Symbol# 2: "_cnt"
394: Type = int
395: String index = 29
396: Storage class = Info Index = 4
397: Symbol type = Member Value = 0
398:
399: Symbol# 3: "_ptr"
400: Type = ptr to char
401: String index = 34
402: Storage class = Info Index = 15
403: Symbol type = Member Value = 32
404:
405: Symbol# 4: "_base"
406: Type = ptr to char
407: String index = 39
408: Storage class = Info Index = 16
409: Symbol type = Member Value = 64
410:
411: Symbol# 5: "_bufsiz"
412: Type = int
413: String index = 45
414: Storage class = Info Index = 4
415: Symbol type = Member Value = 96
416:
417: Symbol# 6: "_flag"
418: Type = short
419: String index = 53
420: Storage class = Info Index = 3
421: Symbol type = Member Value = 128
422:
423: Symbol# 7: "_file"
424: Type = char
425: String index = 59
426: Storage class = Info Index = 2
427: Symbol type = Member Value = 144
428:
429: Symbol# 8: ""
430: First symbol = 1
431: String index = 0
432: Storage class = Info Index = 1
433: Symbol type = End Value = 0
434:
435: Symbol# 9: "/usr/include/stdio.h"
436: First symbol = 0
437: String index = 1
438: Storage class = Text Index = 0
439: Symbol type = End Value = 0
440:
441: There are 25 auxiliary table entries, starting at 642.
442:
443: * #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
444: #15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
445: #16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
446: * #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0]
447: * #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1]
448: * #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
449: * #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4]
450: * #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
451: * #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
452: * #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0]
453: * #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0]
454: * #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
455: * #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
456: * #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
457: * #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
458: * #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
459: * #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
460: * #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
461: * #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
462: * #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
463: * #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
464: * #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
465: * #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
466: * #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
467: * #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
468:
469: There are 0 procedure descriptor entries, starting at 1.
470:
471: There are 20 external symbols, starting at 1152
472:
473: Symbol# 0: "_iob"
474: Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
475: String index = 0 Ifd = 1
476: Storage class = Nil Index = 17
477: Symbol type = Global Value = 60
478:
479: Symbol# 1: "fopen"
480: String index = 5 Ifd = 1
481: Storage class = Nil Index = 1048575
482: Symbol type = Proc Value = 0
483:
484: Symbol# 2: "fdopen"
485: String index = 11 Ifd = 1
486: Storage class = Nil Index = 1048575
487: Symbol type = Proc Value = 0
488:
489: Symbol# 3: "freopen"
490: String index = 18 Ifd = 1
491: Storage class = Nil Index = 1048575
492: Symbol type = Proc Value = 0
493:
494: Symbol# 4: "popen"
495: String index = 26 Ifd = 1
496: Storage class = Nil Index = 1048575
497: Symbol type = Proc Value = 0
498:
499: Symbol# 5: "tmpfile"
500: String index = 32 Ifd = 1
501: Storage class = Nil Index = 1048575
502: Symbol type = Proc Value = 0
503:
504: Symbol# 6: "ftell"
505: String index = 40 Ifd = 1
506: Storage class = Nil Index = 1048575
507: Symbol type = Proc Value = 0
508:
509: Symbol# 7: "rewind"
510: String index = 46 Ifd = 1
511: Storage class = Nil Index = 1048575
512: Symbol type = Proc Value = 0
513:
514: Symbol# 8: "setbuf"
515: String index = 53 Ifd = 1
516: Storage class = Nil Index = 1048575
517: Symbol type = Proc Value = 0
518:
519: Symbol# 9: "setbuffer"
520: String index = 60 Ifd = 1
521: Storage class = Nil Index = 1048575
522: Symbol type = Proc Value = 0
523:
524: Symbol# 10: "setlinebuf"
525: String index = 70 Ifd = 1
526: Storage class = Nil Index = 1048575
527: Symbol type = Proc Value = 0
528:
529: Symbol# 11: "fgets"
530: String index = 81 Ifd = 1
531: Storage class = Nil Index = 1048575
532: Symbol type = Proc Value = 0
533:
534: Symbol# 12: "gets"
535: String index = 87 Ifd = 1
536: Storage class = Nil Index = 1048575
537: Symbol type = Proc Value = 0
538:
539: Symbol# 13: "ctermid"
540: String index = 92 Ifd = 1
541: Storage class = Nil Index = 1048575
542: Symbol type = Proc Value = 0
543:
544: Symbol# 14: "cuserid"
545: String index = 100 Ifd = 1
546: Storage class = Nil Index = 1048575
547: Symbol type = Proc Value = 0
548:
549: Symbol# 15: "tempnam"
550: String index = 108 Ifd = 1
551: Storage class = Nil Index = 1048575
552: Symbol type = Proc Value = 0
553:
554: Symbol# 16: "tmpnam"
555: String index = 116 Ifd = 1
556: Storage class = Nil Index = 1048575
557: Symbol type = Proc Value = 0
558:
559: Symbol# 17: "sprintf"
560: String index = 123 Ifd = 1
561: Storage class = Nil Index = 1048575
562: Symbol type = Proc Value = 0
563:
564: Symbol# 18: "main"
565: Type = int
566: String index = 131 Ifd = 0
567: Storage class = Text Index = 1
568: Symbol type = Proc Value = 0
569:
570: Symbol# 19: "printf"
571: String index = 136 Ifd = 0
572: Storage class = Undefined Index = 1048575
573: Symbol type = Proc Value = 0
574:
575: The following auxiliary table entries were unused:
576:
577: #0 0 0x00000000 void
578: #2 8 0x00000008 char
579: #3 16 0x00000010 short
580: #4 24 0x00000018 int
581: #5 32 0x00000020 long
582: #6 40 0x00000028 float
583: #7 44 0x0000002c double
584: #8 12 0x0000000c unsigned char
585: #9 20 0x00000014 unsigned short
586: #10 28 0x0000001c unsigned int
587: #11 36 0x00000024 unsigned long
588: #14 0 0x00000000 void
589: #15 24 0x00000018 int
590: #19 32 0x00000020 long
591: #20 40 0x00000028 float
592: #21 44 0x0000002c double
593: #22 12 0x0000000c unsigned char
594: #23 20 0x00000014 unsigned short
595: #24 28 0x0000001c unsigned int
596: #25 36 0x00000024 unsigned long
597: #26 48 0x00000030 struct no name { ifd = -1, index = 1048575 }
598:
599: */
600:
601:
1.1.1.7 root 602: #ifdef __STDC__
603: #include <stdarg.h>
604: #else
605: #include <varargs.h>
606: #endif
1.1 root 607: #include "config.h"
1.1.1.4 root 608: #include <stdio.h>
1.1 root 609:
610: #ifndef __SABER__
611: #define saber_stop()
612: #endif
613:
614: #ifndef __LINE__
615: #define __LINE__ 0
616: #endif
617:
618: #ifdef __STDC__
619: typedef void *PTR_T;
620: typedef const void *CPTR_T;
621: #define __proto(x) x
1.1.1.7 root 622: #ifndef VPROTO
623: #define PVPROTO(ARGS) ARGS
624: #define VPROTO(ARGS) ARGS
625: #define VA_START(va_list,var) va_start(va_list,var)
626: #endif
1.1 root 627: #else
628:
1.1.1.2 root 629: #if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
1.1 root 630: typedef void *PTR_T;
631: typedef void *CPTR_T;
632:
633: #else
1.1.1.2 root 634: typedef char *PTR_T; /* Ultrix 3.1 */
1.1 root 635: typedef char *CPTR_T;
636: #endif
637:
638: #define __proto(x) ()
639: #define const
1.1.1.7 root 640: #ifndef VPROTO
641: #define PVPROTO(ARGS) ()
642: #define VPROTO(ARGS) (va_alist) va_dcl
643: #define VA_START(va_list,var) va_start(va_list)
644: #endif
1.1 root 645: #endif
646:
647: /* Do to size_t being defined in sys/types.h and different
648: in stddef.h, we have to do this by hand..... Note, these
649: types are correct for MIPS based systems, and may not be
650: correct for other systems. Ultrix 4.0 and Silicon Graphics
651: have this fixed, but since the following is correct, and
652: the fact that including stddef.h gets you GCC's version
653: instead of the standard one it's not worth it to fix it. */
654:
1.1.1.4 root 655: #if defined(__OSF1__) || defined(__OSF__) || defined(__osf__)
656: #define Size_t long unsigned int
657: #else
1.1 root 658: #define Size_t unsigned int
1.1.1.4 root 659: #endif
1.1.1.6 root 660: #define Ptrdiff_t long
1.1 root 661:
662: /* The following might be called from obstack or malloc,
663: so they can't be static. */
664:
665: extern void pfatal_with_name
666: __proto((char *));
667: extern void fancy_abort __proto((void));
1.1.1.2 root 668: void botch __proto((const char *));
1.1 root 669: extern PTR_T xmalloc __proto((Size_t));
670: extern PTR_T xcalloc __proto((Size_t, Size_t));
671: extern PTR_T xrealloc __proto((PTR_T, Size_t));
672: extern void xfree __proto((PTR_T));
673:
1.1.1.7 root 674: #ifdef HAVE_VPRINTF
1.1.1.8 ! root 675: extern void fatal PVPROTO((const char *format, ...));
! 676: extern void error PVPROTO((const char *format, ...));
1.1.1.7 root 677: #else
678: /* We must not provide any prototype here, even if ANSI C. */
679: extern void fatal __proto(());
680: extern void error __proto(());
681: #endif
1.1 root 682:
683:
684: #ifndef MIPS_DEBUGGING_INFO
685:
686: static int line_number;
687: static int cur_line_start;
688: static int debug;
689: static int had_errors;
690: static char *progname;
691: static char *input_name;
692:
693: int
694: main ()
695: {
696: fprintf (stderr, "Mips-tfile should only be run on a MIPS computer!\n");
697: exit (1);
698: }
699:
700: #else /* MIPS_DEBUGGING defined */
701:
1.1.1.4 root 702: /* The local and global symbols have a field index, so undo any defines
703: of index -> strchr and rindex -> strrchr. */
704:
705: #undef rindex
706: #undef index
1.1 root 707:
708: #include <sys/types.h>
709: #include <string.h>
710: #include <ctype.h>
711: #include <fcntl.h>
712: #include <errno.h>
713: #include <signal.h>
714: #include <sys/stat.h>
715:
1.1.1.4 root 716: #ifndef CROSS_COMPILE
717: #include <a.out.h>
718: #else
1.1.1.6 root 719: #include "mips/a.out.h"
720: #endif /* CROSS_COMPILE */
1.1.1.4 root 721:
1.1.1.2 root 722: #if defined (USG) || defined (NO_STAB_H)
1.1 root 723: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
724: #else
725: #include <stab.h> /* On BSD, use the system's stab.h. */
726: #endif /* not USG */
727:
728: #ifdef __GNU_STAB__
729: #define STAB_CODE_TYPE enum __stab_debug_code
730: #else
731: #define STAB_CODE_TYPE int
732: #endif
733:
734: #ifdef _OSF_SOURCE
735: #define HAS_STDLIB_H
736: #define HAS_UNISTD_H
737: #endif
738:
739: #ifdef HAS_STDLIB_H
740: #include <stdlib.h>
741: #endif
742:
743: #ifdef HAS_UNISTD_H
744: #include <unistd.h>
745: #endif
746:
747: #ifndef errno
748: extern int errno; /* MIPS errno.h doesn't declare this */
749: #endif
750:
751: #ifndef MALLOC_CHECK
752: #ifdef __SABER__
753: #define MALLOC_CHECK
754: #endif
755: #endif
756:
757: #define IS_ASM_IDENT(ch) \
758: (isalnum (ch) || (ch) == '_' || (ch) == '.' || (ch) == '$')
759:
760:
1.1.1.3 root 761: /* Redefinition of of storage classes as an enumeration for better
1.1 root 762: debugging. */
763:
764: typedef enum sc {
765: sc_Nil = scNil, /* no storage class */
766: sc_Text = scText, /* text symbol */
767: sc_Data = scData, /* initialized data symbol */
768: sc_Bss = scBss, /* un-initialized data symbol */
769: sc_Register = scRegister, /* value of symbol is register number */
770: sc_Abs = scAbs, /* value of symbol is absolute */
771: sc_Undefined = scUndefined, /* who knows? */
772: sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
773: sc_Bits = scBits, /* this is a bit field */
774: sc_CdbSystem = scCdbSystem, /* value is IN CDB's address space */
775: sc_RegImage = scRegImage, /* register value saved on stack */
776: sc_Info = scInfo, /* symbol contains debugger information */
777: sc_UserStruct = scUserStruct, /* addr in struct user for current process */
778: sc_SData = scSData, /* load time only small data */
779: sc_SBss = scSBss, /* load time only small common */
780: sc_RData = scRData, /* load time only read only data */
781: sc_Var = scVar, /* Var parameter (fortran,pascal) */
782: sc_Common = scCommon, /* common variable */
783: sc_SCommon = scSCommon, /* small common */
784: sc_VarRegister = scVarRegister, /* Var parameter in a register */
785: sc_Variant = scVariant, /* Variant record */
786: sc_SUndefined = scSUndefined, /* small undefined(external) data */
787: sc_Init = scInit, /* .init section symbol */
788: sc_Max = scMax /* Max storage class+1 */
789: } sc_t;
790:
791: /* Redefinition of symbol type. */
792:
793: typedef enum st {
794: st_Nil = stNil, /* Nuthin' special */
795: st_Global = stGlobal, /* external symbol */
796: st_Static = stStatic, /* static */
797: st_Param = stParam, /* procedure argument */
798: st_Local = stLocal, /* local variable */
799: st_Label = stLabel, /* label */
800: st_Proc = stProc, /* " " Procedure */
1.1.1.3 root 801: st_Block = stBlock, /* beginning of block */
1.1 root 802: st_End = stEnd, /* end (of anything) */
803: st_Member = stMember, /* member (of anything - struct/union/enum */
804: st_Typedef = stTypedef, /* type definition */
805: st_File = stFile, /* file name */
806: st_RegReloc = stRegReloc, /* register relocation */
807: st_Forward = stForward, /* forwarding address */
808: st_StaticProc = stStaticProc, /* load time only static procs */
809: st_Constant = stConstant, /* const */
810: st_Str = stStr, /* string */
811: st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
812: st_Expr = stExpr, /* 2+2 vs. 4 */
1.1.1.3 root 813: st_Type = stType, /* post-coercion SER */
1.1 root 814: st_Max = stMax /* max type+1 */
815: } st_t;
816:
817: /* Redefinition of type qualifiers. */
818:
819: typedef enum tq {
820: tq_Nil = tqNil, /* bt is what you see */
821: tq_Ptr = tqPtr, /* pointer */
822: tq_Proc = tqProc, /* procedure */
823: tq_Array = tqArray, /* duh */
824: tq_Far = tqFar, /* longer addressing - 8086/8 land */
825: tq_Vol = tqVol, /* volatile */
826: tq_Max = tqMax /* Max type qualifier+1 */
827: } tq_t;
828:
829: /* Redefinition of basic types. */
830:
831: typedef enum bt {
832: bt_Nil = btNil, /* undefined */
833: bt_Adr = btAdr, /* address - integer same size as pointer */
834: bt_Char = btChar, /* character */
835: bt_UChar = btUChar, /* unsigned character */
836: bt_Short = btShort, /* short */
837: bt_UShort = btUShort, /* unsigned short */
838: bt_Int = btInt, /* int */
839: bt_UInt = btUInt, /* unsigned int */
840: bt_Long = btLong, /* long */
841: bt_ULong = btULong, /* unsigned long */
842: bt_Float = btFloat, /* float (real) */
843: bt_Double = btDouble, /* Double (real) */
844: bt_Struct = btStruct, /* Structure (Record) */
845: bt_Union = btUnion, /* Union (variant) */
846: bt_Enum = btEnum, /* Enumerated */
847: bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
848: bt_Range = btRange, /* subrange of int */
849: bt_Set = btSet, /* pascal sets */
850: bt_Complex = btComplex, /* fortran complex */
851: bt_DComplex = btDComplex, /* fortran double complex */
852: bt_Indirect = btIndirect, /* forward or unnamed typedef */
853: bt_FixedDec = btFixedDec, /* Fixed Decimal */
854: bt_FloatDec = btFloatDec, /* Float Decimal */
855: bt_String = btString, /* Varying Length Character String */
856: bt_Bit = btBit, /* Aligned Bit String */
857: bt_Picture = btPicture, /* Picture */
858:
859: #ifdef btVoid
860: bt_Void = btVoid, /* Void */
861: #else
862: #define bt_Void bt_Nil
863: #endif
864:
865: bt_Max = btMax /* Max basic type+1 */
866: } bt_t;
867:
868:
869:
870: /* Basic COFF storage classes. */
871: enum coff_storage {
872: C_EFCN = -1,
873: C_NULL = 0,
874: C_AUTO = 1,
875: C_EXT = 2,
876: C_STAT = 3,
877: C_REG = 4,
878: C_EXTDEF = 5,
879: C_LABEL = 6,
880: C_ULABEL = 7,
881: C_MOS = 8,
882: C_ARG = 9,
883: C_STRTAG = 10,
884: C_MOU = 11,
885: C_UNTAG = 12,
886: C_TPDEF = 13,
887: C_USTATIC = 14,
888: C_ENTAG = 15,
889: C_MOE = 16,
890: C_REGPARM = 17,
891: C_FIELD = 18,
892: C_BLOCK = 100,
893: C_FCN = 101,
894: C_EOS = 102,
895: C_FILE = 103,
896: C_LINE = 104,
897: C_ALIAS = 105,
898: C_HIDDEN = 106,
899: C_MAX = 107
900: } coff_storage_t;
901:
902: /* Regular COFF fundamental type. */
903: typedef enum coff_type {
904: T_NULL = 0,
905: T_ARG = 1,
906: T_CHAR = 2,
907: T_SHORT = 3,
908: T_INT = 4,
909: T_LONG = 5,
910: T_FLOAT = 6,
911: T_DOUBLE = 7,
912: T_STRUCT = 8,
913: T_UNION = 9,
914: T_ENUM = 10,
915: T_MOE = 11,
916: T_UCHAR = 12,
917: T_USHORT = 13,
918: T_UINT = 14,
919: T_ULONG = 15,
920: T_MAX = 16
921: } coff_type_t;
922:
923: /* Regular COFF derived types. */
924: typedef enum coff_dt {
925: DT_NON = 0,
926: DT_PTR = 1,
927: DT_FCN = 2,
928: DT_ARY = 3,
929: DT_MAX = 4
930: } coff_dt_t;
931:
932: #define N_BTMASK 017 /* bitmask to isolate basic type */
933: #define N_TMASK 003 /* bitmask to isolate derived type */
934: #define N_BT_SHIFT 4 /* # bits to shift past basic type */
935: #define N_TQ_SHIFT 2 /* # bits to shift derived types */
936: #define N_TQ 6 /* # of type qualifiers */
937:
938: /* States for whether to hash type or not. */
939: typedef enum hash_state {
940: hash_no = 0, /* don't hash type */
941: hash_yes = 1, /* ok to hash type, or use previous hash */
942: hash_record = 2 /* ok to record hash, but don't use prev. */
943: } hash_state_t;
944:
945:
946: /* Types of different sized allocation requests. */
947: enum alloc_type {
948: alloc_type_none, /* dummy value */
949: alloc_type_scope, /* nested scopes linked list */
950: alloc_type_vlinks, /* glue linking pages in varray */
951: alloc_type_shash, /* string hash element */
952: alloc_type_thash, /* type hash element */
953: alloc_type_tag, /* struct/union/tag element */
954: alloc_type_forward, /* element to hold unknown tag */
955: alloc_type_thead, /* head of type hash list */
956: alloc_type_varray, /* general varray allocation */
957: alloc_type_last /* last+1 element for array bounds */
958: };
959:
960:
1.1.1.6 root 961: #define WORD_ALIGN(x) (((x) + (sizeof (long) - 1)) & ~ (sizeof (long) - 1))
1.1 root 962: #define DWORD_ALIGN(x) (((x) + 7) & ~7)
963:
964:
965: /* Structures to provide n-number of virtual arrays, each of which can
966: grow linearly, and which are written in the object file as sequential
967: pages. On systems with a BSD malloc that define USE_MALLOC, the
968: MAX_CLUSTER_PAGES should be 1 less than a power of two, since malloc
969: adds it's overhead, and rounds up to the next power of 2. Pages are
970: linked together via a linked list.
971:
972: If PAGE_SIZE is > 4096, the string length in the shash_t structure
973: can't be represented (assuming there are strings > 4096 bytes). */
974:
975: #ifndef PAGE_SIZE
976: #define PAGE_SIZE 4096 /* size of varray pages */
977: #endif
978:
979: #define PAGE_USIZE ((Size_t)PAGE_SIZE)
980:
981:
982: #ifndef MAX_CLUSTER_PAGES /* # pages to get from system */
983: #ifndef USE_MALLOC /* in one memory request */
984: #define MAX_CLUSTER_PAGES 64
985: #else
986: #define MAX_CLUSTER_PAGES 63
987: #endif
988: #endif
989:
990:
991: /* Linked list connecting separate page allocations. */
992: typedef struct vlinks {
993: struct vlinks *prev; /* previous set of pages */
994: struct vlinks *next; /* next set of pages */
995: union page *datum; /* start of page */
996: unsigned long start_index; /* starting index # of page */
997: } vlinks_t;
998:
999:
1000: /* Virtual array header. */
1001: typedef struct varray {
1002: vlinks_t *first; /* first page link */
1003: vlinks_t *last; /* last page link */
1004: unsigned long num_allocated; /* # objects allocated */
1005: unsigned short object_size; /* size in bytes of each object */
1006: unsigned short objects_per_page; /* # objects that can fit on a page */
1007: unsigned short objects_last_page; /* # objects allocated on last page */
1008: } varray_t;
1009:
1010: #ifndef MALLOC_CHECK
1011: #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
1012: #else
1013: #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
1014: #endif
1015:
1016: #define INIT_VARRAY(type) { /* macro to initialize a varray */ \
1017: (vlinks_t *)0, /* first */ \
1018: (vlinks_t *)0, /* last */ \
1019: 0, /* num_allocated */ \
1020: sizeof (type), /* object_size */ \
1021: OBJECTS_PER_PAGE (type), /* objects_per_page */ \
1022: OBJECTS_PER_PAGE (type), /* objects_last_page */ \
1023: }
1024:
1025: /* Master type for indexes within the symbol table. */
1026: typedef unsigned long symint_t;
1027:
1028:
1029: /* Linked list support for nested scopes (file, block, structure, etc.). */
1030: typedef struct scope {
1031: struct scope *prev; /* previous scope level */
1032: struct scope *free; /* free list pointer */
1033: SYMR *lsym; /* pointer to local symbol node */
1034: symint_t lnumber; /* lsym index */
1035: st_t type; /* type of the node */
1036: } scope_t;
1037:
1038:
1039: /* Forward reference list for tags referenced, but not yet defined. */
1040: typedef struct forward {
1041: struct forward *next; /* next forward reference */
1042: struct forward *free; /* free list pointer */
1043: AUXU *ifd_ptr; /* pointer to store file index */
1044: AUXU *index_ptr; /* pointer to store symbol index */
1045: AUXU *type_ptr; /* pointer to munge type info */
1046: } forward_t;
1047:
1048:
1049: /* Linked list support for tags. The first tag in the list is always
1050: the current tag for that block. */
1051: typedef struct tag {
1052: struct tag *free; /* free list pointer */
1053: struct shash *hash_ptr; /* pointer to the hash table head */
1054: struct tag *same_name; /* tag with same name in outer scope */
1055: struct tag *same_block; /* next tag defined in the same block. */
1056: struct forward *forward_ref; /* list of forward references */
1057: bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
1058: symint_t ifd; /* file # tag defined in */
1.1.1.4 root 1059: symint_t indx; /* index within file's local symbols */
1.1 root 1060: } tag_t;
1061:
1062:
1063: /* Head of a block's linked list of tags. */
1064: typedef struct thead {
1065: struct thead *prev; /* previous block */
1066: struct thead *free; /* free list pointer */
1067: struct tag *first_tag; /* first tag in block defined */
1068: } thead_t;
1069:
1070:
1071: /* Union containing pointers to each the small structures which are freed up. */
1072: typedef union small_free {
1073: scope_t *f_scope; /* scope structure */
1074: thead_t *f_thead; /* tag head structure */
1075: tag_t *f_tag; /* tag element structure */
1076: forward_t *f_forward; /* forward tag reference */
1077: } small_free_t;
1078:
1079:
1080: /* String hash table support. The size of the hash table must fit
1081: within a page. */
1082:
1083: #ifndef SHASH_SIZE
1084: #define SHASH_SIZE 1009
1085: #endif
1086:
1087: #define HASH_LEN_MAX ((1 << 12) - 1) /* Max length we can store */
1088:
1089: typedef struct shash {
1090: struct shash *next; /* next hash value */
1091: char *string; /* string we are hashing */
1092: symint_t len; /* string length */
1.1.1.4 root 1093: symint_t indx; /* index within string table */
1.1 root 1094: EXTR *esym_ptr; /* global symbol pointer */
1095: SYMR *sym_ptr; /* local symbol pointer */
1096: SYMR *end_ptr; /* symbol pointer to end block */
1097: tag_t *tag_ptr; /* tag pointer */
1098: PDR *proc_ptr; /* procedure descriptor pointer */
1099: } shash_t;
1100:
1101:
1102: /* Type hash table support. The size of the hash table must fit
1103: within a page with the other extended file descriptor information.
1104: Because unique types which are hashed are fewer in number than
1105: strings, we use a smaller hash value. */
1106:
1107: #ifndef THASH_SIZE
1108: #define THASH_SIZE 113
1109: #endif
1110:
1111: typedef struct thash {
1112: struct thash *next; /* next hash value */
1113: AUXU type; /* type we are hashing */
1.1.1.4 root 1114: symint_t indx; /* index within string table */
1.1 root 1115: } thash_t;
1116:
1117:
1118: /* Extended file descriptor that contains all of the support necessary
1119: to add things to each file separately. */
1120: typedef struct efdr {
1121: FDR fdr; /* File header to be written out */
1122: FDR *orig_fdr; /* original file header */
1123: char *name; /* filename */
1124: int name_len; /* length of the filename */
1125: symint_t void_type; /* aux. pointer to 'void' type */
1126: symint_t int_type; /* aux. pointer to 'int' type */
1127: scope_t *cur_scope; /* current nested scopes */
1128: symint_t file_index; /* current file number */
1129: int nested_scopes; /* # nested scopes */
1130: varray_t strings; /* local strings */
1131: varray_t symbols; /* local symbols */
1132: varray_t procs; /* procedures */
1133: varray_t aux_syms; /* auxiliary symbols */
1134: struct efdr *next_file; /* next file descriptor */
1135: /* string/type hash tables */
1136: shash_t **shash_head; /* string hash table */
1137: thash_t *thash_head[THASH_SIZE];
1138: } efdr_t;
1139:
1140: /* Pre-initialized extended file structure. */
1141: static efdr_t init_file =
1142: {
1143: { /* FDR structure */
1144: 0, /* adr: memory address of beginning of file */
1145: 0, /* rss: file name (of source, if known) */
1146: 0, /* issBase: file's string space */
1147: 0, /* cbSs: number of bytes in the ss */
1148: 0, /* isymBase: beginning of symbols */
1149: 0, /* csym: count file's of symbols */
1150: 0, /* ilineBase: file's line symbols */
1151: 0, /* cline: count of file's line symbols */
1152: 0, /* ioptBase: file's optimization entries */
1153: 0, /* copt: count of file's optimization entries */
1154: 0, /* ipdFirst: start of procedures for this file */
1155: 0, /* cpd: count of procedures for this file */
1156: 0, /* iauxBase: file's auxiliary entries */
1157: 0, /* caux: count of file's auxiliary entries */
1158: 0, /* rfdBase: index into the file indirect table */
1159: 0, /* crfd: count file indirect entries */
1160: langC, /* lang: language for this file */
1161: 1, /* fMerge: whether this file can be merged */
1162: 0, /* fReadin: true if read in (not just created) */
1.1.1.8 ! root 1163: #ifdef HOST_WORDS_BIG_ENDIAN
1.1 root 1164: 1, /* fBigendian: if 1, compiled on big endian machine */
1165: #else
1166: 0, /* fBigendian: if 1, compiled on big endian machine */
1167: #endif
1168: GLEVEL_2, /* glevel: level this file was compiled with */
1169: 0, /* reserved: reserved for future use */
1170: 0, /* cbLineOffset: byte offset from header for this file ln's */
1171: 0, /* cbLine: size of lines for this file */
1172: },
1173:
1174: (FDR *)0, /* orig_fdr: original file header pointer */
1175: (char *)0, /* name: pointer to filename */
1176: 0, /* name_len: length of filename */
1177: 0, /* void_type: ptr to aux node for void type */
1178: 0, /* int_type: ptr to aux node for int type */
1179: (scope_t *)0, /* cur_scope: current scope being processed */
1180: 0, /* file_index: current file # */
1181: 0, /* nested_scopes: # nested scopes */
1182: INIT_VARRAY (char), /* strings: local string varray */
1183: INIT_VARRAY (SYMR), /* symbols: local symbols varray */
1184: INIT_VARRAY (PDR), /* procs: procedure varray */
1185: INIT_VARRAY (AUXU), /* aux_syms: auxiliary symbols varray */
1186:
1187: (struct efdr *)0, /* next_file: next file structure */
1188:
1189: (shash_t **)0, /* shash_head: string hash table */
1190: { 0 }, /* thash_head: type hash table */
1191: };
1192:
1193:
1194: static efdr_t *first_file; /* first file descriptor */
1195: static efdr_t **last_file_ptr = &first_file; /* file descriptor tail */
1196:
1197:
1198: /* Union of various things that are held in pages. */
1199: typedef union page {
1200: char byte [ PAGE_SIZE ];
1201: unsigned char ubyte [ PAGE_SIZE ];
1202: efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
1203: FDR ofile [ PAGE_SIZE / sizeof (FDR) ];
1204: PDR proc [ PAGE_SIZE / sizeof (PDR) ];
1205: SYMR sym [ PAGE_SIZE / sizeof (SYMR) ];
1206: EXTR esym [ PAGE_SIZE / sizeof (EXTR) ];
1207: AUXU aux [ PAGE_SIZE / sizeof (AUXU) ];
1208: DNR dense [ PAGE_SIZE / sizeof (DNR) ];
1209: scope_t scope [ PAGE_SIZE / sizeof (scope_t) ];
1210: vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ];
1211: shash_t shash [ PAGE_SIZE / sizeof (shash_t) ];
1212: thash_t thash [ PAGE_SIZE / sizeof (thash_t) ];
1213: tag_t tag [ PAGE_SIZE / sizeof (tag_t) ];
1214: forward_t forward [ PAGE_SIZE / sizeof (forward_t) ];
1215: thead_t thead [ PAGE_SIZE / sizeof (thead_t) ];
1216: } page_t;
1217:
1218:
1219: /* Structure holding allocation information for small sized structures. */
1220: typedef struct alloc_info {
1221: char *alloc_name; /* name of this allocation type (must be first) */
1222: page_t *cur_page; /* current page being allocated from */
1223: small_free_t free_list; /* current free list if any */
1224: int unallocated; /* number of elements unallocated on page */
1225: int total_alloc; /* total number of allocations */
1226: int total_free; /* total number of frees */
1227: int total_pages; /* total number of pages allocated */
1228: } alloc_info_t;
1229:
1230: /* Type information collected together. */
1231: typedef struct type_info {
1232: bt_t basic_type; /* basic type */
1233: coff_type_t orig_type; /* original COFF-based type */
1234: int num_tq; /* # type qualifiers */
1235: int num_dims; /* # dimensions */
1236: int num_sizes; /* # sizes */
1237: int extra_sizes; /* # extra sizes not tied with dims */
1238: tag_t * tag_ptr; /* tag pointer */
1239: int bitfield; /* symbol is a bitfield */
1240: int unknown_tag; /* this is an unknown tag */
1241: tq_t type_qualifiers[N_TQ]; /* type qualifiers (ptr, func, array)*/
1242: symint_t dimensions [N_TQ]; /* dimensions for each array */
1243: symint_t sizes [N_TQ+2]; /* sizes of each array slice + size of
1244: struct/union/enum + bitfield size */
1245: } type_info_t;
1246:
1247: /* Pre-initialized type_info struct. */
1248: static type_info_t type_info_init = {
1249: bt_Nil, /* basic type */
1250: T_NULL, /* original COFF-based type */
1251: 0, /* # type qualifiers */
1252: 0, /* # dimensions */
1253: 0, /* # sizes */
1254: 0, /* sizes not tied with dims */
1255: NULL, /* ptr to tag */
1256: 0, /* bitfield */
1257: 0, /* unknown tag */
1258: { /* type qualifiers */
1259: tq_Nil,
1260: tq_Nil,
1261: tq_Nil,
1262: tq_Nil,
1263: tq_Nil,
1264: tq_Nil,
1265: },
1266: { /* dimensions */
1267: 0,
1268: 0,
1269: 0,
1270: 0,
1271: 0,
1272: 0
1273: },
1274: { /* sizes */
1275: 0,
1276: 0,
1277: 0,
1278: 0,
1279: 0,
1280: 0,
1281: 0,
1282: 0,
1283: },
1284: };
1285:
1286:
1287: /* Global virtual arrays & hash table for external strings as well as
1288: for the tags table and global tables for file descriptors, and
1289: dense numbers. */
1290:
1291: static varray_t file_desc = INIT_VARRAY (efdr_t);
1292: static varray_t dense_num = INIT_VARRAY (DNR);
1293: static varray_t tag_strings = INIT_VARRAY (char);
1294: static varray_t ext_strings = INIT_VARRAY (char);
1295: static varray_t ext_symbols = INIT_VARRAY (EXTR);
1296:
1297: static shash_t *orig_str_hash[SHASH_SIZE];
1298: static shash_t *ext_str_hash [SHASH_SIZE];
1299: static shash_t *tag_hash [SHASH_SIZE];
1300:
1301: /* Static types for int and void. Also, remember the last function's
1302: type (which is set up when we encounter the declaration for the
1303: function, and used when the end block for the function is emitted. */
1304:
1305: static type_info_t int_type_info;
1306: static type_info_t void_type_info;
1307: static type_info_t last_func_type_info;
1308: static EXTR *last_func_eptr;
1309:
1310:
1311: /* Convert COFF basic type to ECOFF basic type. The T_NULL type
1312: really should use bt_Void, but this causes the current ecoff GDB to
1313: issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
1314: 2.0) doesn't understand it, even though the compiler generates it.
1315: Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
1316: suite, but for now go with what works. */
1317:
1318: static bt_t map_coff_types[ (int)T_MAX ] = {
1319: bt_Nil, /* T_NULL */
1320: bt_Nil, /* T_ARG */
1321: bt_Char, /* T_CHAR */
1322: bt_Short, /* T_SHORT */
1323: bt_Int, /* T_INT */
1324: bt_Long, /* T_LONG */
1325: bt_Float, /* T_FLOAT */
1326: bt_Double, /* T_DOUBLE */
1327: bt_Struct, /* T_STRUCT */
1328: bt_Union, /* T_UNION */
1329: bt_Enum, /* T_ENUM */
1330: bt_Enum, /* T_MOE */
1331: bt_UChar, /* T_UCHAR */
1332: bt_UShort, /* T_USHORT */
1333: bt_UInt, /* T_UINT */
1334: bt_ULong /* T_ULONG */
1335: };
1336:
1337: /* Convert COFF storage class to ECOFF storage class. */
1338: static sc_t map_coff_storage[ (int)C_MAX ] = {
1339: sc_Nil, /* 0: C_NULL */
1340: sc_Abs, /* 1: C_AUTO auto var */
1341: sc_Undefined, /* 2: C_EXT external */
1342: sc_Data, /* 3: C_STAT static */
1343: sc_Register, /* 4: C_REG register */
1344: sc_Undefined, /* 5: C_EXTDEF ??? */
1345: sc_Text, /* 6: C_LABEL label */
1346: sc_Text, /* 7: C_ULABEL user label */
1347: sc_Info, /* 8: C_MOS member of struct */
1348: sc_Abs, /* 9: C_ARG argument */
1349: sc_Info, /* 10: C_STRTAG struct tag */
1350: sc_Info, /* 11: C_MOU member of union */
1351: sc_Info, /* 12: C_UNTAG union tag */
1352: sc_Info, /* 13: C_TPDEF typedef */
1353: sc_Data, /* 14: C_USTATIC ??? */
1354: sc_Info, /* 15: C_ENTAG enum tag */
1355: sc_Info, /* 16: C_MOE member of enum */
1356: sc_Register, /* 17: C_REGPARM register parameter */
1357: sc_Bits, /* 18; C_FIELD bitfield */
1358: sc_Nil, /* 19 */
1359: sc_Nil, /* 20 */
1360: sc_Nil, /* 21 */
1361: sc_Nil, /* 22 */
1362: sc_Nil, /* 23 */
1363: sc_Nil, /* 24 */
1364: sc_Nil, /* 25 */
1365: sc_Nil, /* 26 */
1366: sc_Nil, /* 27 */
1367: sc_Nil, /* 28 */
1368: sc_Nil, /* 29 */
1369: sc_Nil, /* 30 */
1370: sc_Nil, /* 31 */
1371: sc_Nil, /* 32 */
1372: sc_Nil, /* 33 */
1373: sc_Nil, /* 34 */
1374: sc_Nil, /* 35 */
1375: sc_Nil, /* 36 */
1376: sc_Nil, /* 37 */
1377: sc_Nil, /* 38 */
1378: sc_Nil, /* 39 */
1379: sc_Nil, /* 40 */
1380: sc_Nil, /* 41 */
1381: sc_Nil, /* 42 */
1382: sc_Nil, /* 43 */
1383: sc_Nil, /* 44 */
1384: sc_Nil, /* 45 */
1385: sc_Nil, /* 46 */
1386: sc_Nil, /* 47 */
1387: sc_Nil, /* 48 */
1388: sc_Nil, /* 49 */
1389: sc_Nil, /* 50 */
1390: sc_Nil, /* 51 */
1391: sc_Nil, /* 52 */
1392: sc_Nil, /* 53 */
1393: sc_Nil, /* 54 */
1394: sc_Nil, /* 55 */
1395: sc_Nil, /* 56 */
1396: sc_Nil, /* 57 */
1397: sc_Nil, /* 58 */
1398: sc_Nil, /* 59 */
1399: sc_Nil, /* 60 */
1400: sc_Nil, /* 61 */
1401: sc_Nil, /* 62 */
1402: sc_Nil, /* 63 */
1403: sc_Nil, /* 64 */
1404: sc_Nil, /* 65 */
1405: sc_Nil, /* 66 */
1406: sc_Nil, /* 67 */
1407: sc_Nil, /* 68 */
1408: sc_Nil, /* 69 */
1409: sc_Nil, /* 70 */
1410: sc_Nil, /* 71 */
1411: sc_Nil, /* 72 */
1412: sc_Nil, /* 73 */
1413: sc_Nil, /* 74 */
1414: sc_Nil, /* 75 */
1415: sc_Nil, /* 76 */
1416: sc_Nil, /* 77 */
1417: sc_Nil, /* 78 */
1418: sc_Nil, /* 79 */
1419: sc_Nil, /* 80 */
1420: sc_Nil, /* 81 */
1421: sc_Nil, /* 82 */
1422: sc_Nil, /* 83 */
1423: sc_Nil, /* 84 */
1424: sc_Nil, /* 85 */
1425: sc_Nil, /* 86 */
1426: sc_Nil, /* 87 */
1427: sc_Nil, /* 88 */
1428: sc_Nil, /* 89 */
1429: sc_Nil, /* 90 */
1430: sc_Nil, /* 91 */
1431: sc_Nil, /* 92 */
1432: sc_Nil, /* 93 */
1433: sc_Nil, /* 94 */
1434: sc_Nil, /* 95 */
1435: sc_Nil, /* 96 */
1436: sc_Nil, /* 97 */
1437: sc_Nil, /* 98 */
1438: sc_Nil, /* 99 */
1439: sc_Text, /* 100: C_BLOCK block start/end */
1440: sc_Text, /* 101: C_FCN function start/end */
1441: sc_Info, /* 102: C_EOS end of struct/union/enum */
1442: sc_Nil, /* 103: C_FILE file start */
1443: sc_Nil, /* 104: C_LINE line number */
1444: sc_Nil, /* 105: C_ALIAS combined type info */
1445: sc_Nil, /* 106: C_HIDDEN ??? */
1446: };
1447:
1448: /* Convert COFF storage class to ECOFF symbol type. */
1449: static st_t map_coff_sym_type[ (int)C_MAX ] = {
1450: st_Nil, /* 0: C_NULL */
1451: st_Local, /* 1: C_AUTO auto var */
1452: st_Global, /* 2: C_EXT external */
1453: st_Static, /* 3: C_STAT static */
1454: st_Local, /* 4: C_REG register */
1455: st_Global, /* 5: C_EXTDEF ??? */
1456: st_Label, /* 6: C_LABEL label */
1457: st_Label, /* 7: C_ULABEL user label */
1458: st_Member, /* 8: C_MOS member of struct */
1459: st_Param, /* 9: C_ARG argument */
1460: st_Block, /* 10: C_STRTAG struct tag */
1461: st_Member, /* 11: C_MOU member of union */
1462: st_Block, /* 12: C_UNTAG union tag */
1463: st_Typedef, /* 13: C_TPDEF typedef */
1464: st_Static, /* 14: C_USTATIC ??? */
1465: st_Block, /* 15: C_ENTAG enum tag */
1466: st_Member, /* 16: C_MOE member of enum */
1467: st_Param, /* 17: C_REGPARM register parameter */
1468: st_Member, /* 18; C_FIELD bitfield */
1469: st_Nil, /* 19 */
1470: st_Nil, /* 20 */
1471: st_Nil, /* 21 */
1472: st_Nil, /* 22 */
1473: st_Nil, /* 23 */
1474: st_Nil, /* 24 */
1475: st_Nil, /* 25 */
1476: st_Nil, /* 26 */
1477: st_Nil, /* 27 */
1478: st_Nil, /* 28 */
1479: st_Nil, /* 29 */
1480: st_Nil, /* 30 */
1481: st_Nil, /* 31 */
1482: st_Nil, /* 32 */
1483: st_Nil, /* 33 */
1484: st_Nil, /* 34 */
1485: st_Nil, /* 35 */
1486: st_Nil, /* 36 */
1487: st_Nil, /* 37 */
1488: st_Nil, /* 38 */
1489: st_Nil, /* 39 */
1490: st_Nil, /* 40 */
1491: st_Nil, /* 41 */
1492: st_Nil, /* 42 */
1493: st_Nil, /* 43 */
1494: st_Nil, /* 44 */
1495: st_Nil, /* 45 */
1496: st_Nil, /* 46 */
1497: st_Nil, /* 47 */
1498: st_Nil, /* 48 */
1499: st_Nil, /* 49 */
1500: st_Nil, /* 50 */
1501: st_Nil, /* 51 */
1502: st_Nil, /* 52 */
1503: st_Nil, /* 53 */
1504: st_Nil, /* 54 */
1505: st_Nil, /* 55 */
1506: st_Nil, /* 56 */
1507: st_Nil, /* 57 */
1508: st_Nil, /* 58 */
1509: st_Nil, /* 59 */
1510: st_Nil, /* 60 */
1511: st_Nil, /* 61 */
1512: st_Nil, /* 62 */
1513: st_Nil, /* 63 */
1514: st_Nil, /* 64 */
1515: st_Nil, /* 65 */
1516: st_Nil, /* 66 */
1517: st_Nil, /* 67 */
1518: st_Nil, /* 68 */
1519: st_Nil, /* 69 */
1520: st_Nil, /* 70 */
1521: st_Nil, /* 71 */
1522: st_Nil, /* 72 */
1523: st_Nil, /* 73 */
1524: st_Nil, /* 74 */
1525: st_Nil, /* 75 */
1526: st_Nil, /* 76 */
1527: st_Nil, /* 77 */
1528: st_Nil, /* 78 */
1529: st_Nil, /* 79 */
1530: st_Nil, /* 80 */
1531: st_Nil, /* 81 */
1532: st_Nil, /* 82 */
1533: st_Nil, /* 83 */
1534: st_Nil, /* 84 */
1535: st_Nil, /* 85 */
1536: st_Nil, /* 86 */
1537: st_Nil, /* 87 */
1538: st_Nil, /* 88 */
1539: st_Nil, /* 89 */
1540: st_Nil, /* 90 */
1541: st_Nil, /* 91 */
1542: st_Nil, /* 92 */
1543: st_Nil, /* 93 */
1544: st_Nil, /* 94 */
1545: st_Nil, /* 95 */
1546: st_Nil, /* 96 */
1547: st_Nil, /* 97 */
1548: st_Nil, /* 98 */
1549: st_Nil, /* 99 */
1550: st_Block, /* 100: C_BLOCK block start/end */
1551: st_Proc, /* 101: C_FCN function start/end */
1552: st_End, /* 102: C_EOS end of struct/union/enum */
1553: st_File, /* 103: C_FILE file start */
1554: st_Nil, /* 104: C_LINE line number */
1555: st_Nil, /* 105: C_ALIAS combined type info */
1556: st_Nil, /* 106: C_HIDDEN ??? */
1557: };
1558:
1559: /* Map COFF derived types to ECOFF type qualifiers. */
1560: static tq_t map_coff_derived_type[ (int)DT_MAX ] = {
1561: tq_Nil, /* 0: DT_NON no more qualifiers */
1562: tq_Ptr, /* 1: DT_PTR pointer */
1563: tq_Proc, /* 2: DT_FCN function */
1564: tq_Array, /* 3: DT_ARY array */
1565: };
1566:
1567:
1568: /* Keep track of different sized allocation requests. */
1569: static alloc_info_t alloc_counts[ (int)alloc_type_last ];
1570:
1571:
1572: /* Pointers and such to the original symbol table that is read in. */
1573: static struct filehdr orig_file_header; /* global object file header */
1574:
1575: static HDRR orig_sym_hdr; /* symbolic header on input */
1576: static char *orig_linenum; /* line numbers */
1577: static DNR *orig_dense; /* dense numbers */
1578: static PDR *orig_procs; /* procedures */
1579: static SYMR *orig_local_syms; /* local symbols */
1580: static OPTR *orig_opt_syms; /* optimization symbols */
1581: static AUXU *orig_aux_syms; /* auxiliary symbols */
1582: static char *orig_local_strs; /* local strings */
1583: static char *orig_ext_strs; /* external strings */
1584: static FDR *orig_files; /* file descriptors */
1585: static symint_t *orig_rfds; /* relative file desc's */
1586: static EXTR *orig_ext_syms; /* external symbols */
1587:
1588: /* Macros to convert an index into a given object within the original
1589: symbol table. */
1590: #define CHECK(num,max,str) \
1591: (((unsigned long)num > (unsigned long)max) ? out_of_bounds (num, max, str, __LINE__) : 0)
1592:
1.1.1.4 root 1593: #define ORIG_LINENUM(indx) (CHECK ((indx), orig_sym_hdr.cbLine, "line#"), (indx) + orig_linenum)
1594: #define ORIG_DENSE(indx) (CHECK ((indx), orig_sym_hdr.idnMax, "dense"), (indx) + orig_dense)
1595: #define ORIG_PROCS(indx) (CHECK ((indx), orig_sym_hdr.ipdMax, "procs"), (indx) + orig_procs)
1596: #define ORIG_FILES(indx) (CHECK ((indx), orig_sym_hdr.ifdMax, "funcs"), (indx) + orig_files)
1597: #define ORIG_LSYMS(indx) (CHECK ((indx), orig_sym_hdr.isymMax, "lsyms"), (indx) + orig_local_syms)
1598: #define ORIG_LSTRS(indx) (CHECK ((indx), orig_sym_hdr.issMax, "lstrs"), (indx) + orig_local_strs)
1599: #define ORIG_ESYMS(indx) (CHECK ((indx), orig_sym_hdr.iextMax, "esyms"), (indx) + orig_ext_syms)
1600: #define ORIG_ESTRS(indx) (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs)
1601: #define ORIG_OPT(indx) (CHECK ((indx), orig_sym_hdr.ioptMax, "opt"), (indx) + orig_opt_syms)
1602: #define ORIG_AUX(indx) (CHECK ((indx), orig_sym_hdr.iauxMax, "aux"), (indx) + orig_aux_syms)
1603: #define ORIG_RFDS(indx) (CHECK ((indx), orig_sym_hdr.crfd, "rfds"), (indx) + orig_rfds)
1.1 root 1604:
1605: /* Various other statics. */
1606: static HDRR symbolic_header; /* symbolic header */
1607: static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */
1608: static PDR *cur_proc_ptr = (PDR *) 0; /* current procedure header */
1609: static SYMR *cur_oproc_begin = (SYMR *) 0; /* original proc. sym begin info */
1610: static SYMR *cur_oproc_end = (SYMR *) 0; /* original proc. sym end info */
1611: static PDR *cur_oproc_ptr = (PDR *) 0; /* current original procedure*/
1612: static thead_t *cur_tag_head = (thead_t *)0; /* current tag head */
1613: static long file_offset = 0; /* current file offset */
1614: static long max_file_offset = 0; /* maximum file offset */
1615: static FILE *object_stream = (FILE *)0; /* file desc. to output .o */
1616: static FILE *obj_in_stream = (FILE *)0; /* file desc. to input .o */
1617: static char *progname = (char *)0; /* program name for errors */
1618: static char *input_name = "stdin"; /* name of input file */
1619: static char *object_name = (char *)0; /* tmp. name of object file */
1620: static char *obj_in_name = (char *)0; /* name of input object file */
1621: static char *cur_line_start = (char *)0; /* current line read in */
1622: static char *cur_line_ptr = (char *)0; /* ptr within current line */
1623: static unsigned cur_line_nbytes = 0; /* # bytes for current line */
1624: static unsigned cur_line_alloc = 0; /* # bytes total in buffer */
1625: static long line_number = 0; /* current input line number */
1626: static int debug = 0; /* trace functions */
1627: static int version = 0; /* print version # */
1628: static int had_errors = 0; /* != 0 if errors were found */
1629: static int rename_output = 0; /* != 0 if rename output file*/
1630: static int delete_input = 0; /* != 0 if delete input after done */
1.1.1.2 root 1631: static int stabs_seen = 0; /* != 0 if stabs have been seen */
1.1 root 1632:
1633:
1634: /* Pseudo symbol to use when putting stabs into the symbol table. */
1635: #ifndef STABS_SYMBOL
1636: #define STABS_SYMBOL "@stabs"
1637: #endif
1638:
1639: static char stabs_symbol[] = STABS_SYMBOL;
1640:
1641:
1642: /* Forward reference for functions. See the definition for more details. */
1643:
1644: #ifndef STATIC
1645: #define STATIC static
1646: #endif
1647:
1648: STATIC int out_of_bounds __proto((symint_t, symint_t, const char *, int));
1649:
1650: STATIC shash_t *hash_string __proto((const char *,
1651: Ptrdiff_t,
1652: shash_t **,
1653: symint_t *));
1654:
1655: STATIC symint_t add_string __proto((varray_t *,
1656: shash_t **,
1657: const char *,
1658: const char *,
1659: shash_t **));
1660:
1661: STATIC symint_t add_local_symbol
1662: __proto((const char *,
1663: const char *,
1664: st_t,
1665: sc_t,
1666: symint_t,
1667: symint_t));
1668:
1669: STATIC symint_t add_ext_symbol __proto((const char *,
1670: const char *,
1671: st_t,
1672: sc_t,
1673: long,
1674: symint_t,
1675: int));
1676:
1677: STATIC symint_t add_aux_sym_symint
1678: __proto((symint_t));
1679:
1680: STATIC symint_t add_aux_sym_rndx
1681: __proto((int, symint_t));
1682:
1683: STATIC symint_t add_aux_sym_tir __proto((type_info_t *,
1684: hash_state_t,
1685: thash_t **));
1686:
1687: STATIC tag_t * get_tag __proto((const char *,
1688: const char *,
1689: symint_t,
1690: bt_t));
1691:
1692: STATIC void add_unknown_tag __proto((tag_t *));
1693:
1694: STATIC void add_procedure __proto((const char *,
1695: const char *));
1696:
1697: STATIC void add_file __proto((const char *,
1698: const char *));
1699:
1700: STATIC void add_bytes __proto((varray_t *,
1701: char *,
1702: Size_t));
1703:
1704: STATIC void add_varray_page __proto((varray_t *));
1705:
1706: STATIC void update_headers __proto((void));
1707:
1708: STATIC void write_varray __proto((varray_t *, off_t, const char *));
1709: STATIC void write_object __proto((void));
1710: STATIC char *st_to_string __proto((st_t));
1711: STATIC char *sc_to_string __proto((sc_t));
1712: STATIC char *read_line __proto((void));
1713: STATIC void parse_input __proto((void));
1.1.1.2 root 1714: STATIC void mark_stabs __proto((const char *));
1.1 root 1715: STATIC void parse_begin __proto((const char *));
1716: STATIC void parse_bend __proto((const char *));
1717: STATIC void parse_def __proto((const char *));
1718: STATIC void parse_end __proto((const char *));
1719: STATIC void parse_ent __proto((const char *));
1720: STATIC void parse_file __proto((const char *));
1721: STATIC void parse_stabs_common
1722: __proto((const char *, const char *, const char *));
1723: STATIC void parse_stabs __proto((const char *));
1724: STATIC void parse_stabn __proto((const char *));
1725: STATIC page_t *read_seek __proto((Size_t, off_t, const char *));
1726: STATIC void copy_object __proto((void));
1727:
1728: STATIC void catch_signal __proto((int));
1729: STATIC page_t *allocate_page __proto((void));
1730:
1731: STATIC page_t *allocate_multiple_pages
1732: __proto((Size_t));
1733:
1734: STATIC void free_multiple_pages
1735: __proto((page_t *, Size_t));
1736:
1737: #ifndef MALLOC_CHECK
1738: STATIC page_t *allocate_cluster
1739: __proto((Size_t));
1740: #endif
1741:
1742: STATIC forward_t *allocate_forward __proto((void));
1743: STATIC scope_t *allocate_scope __proto((void));
1744: STATIC shash_t *allocate_shash __proto((void));
1745: STATIC tag_t *allocate_tag __proto((void));
1746: STATIC thash_t *allocate_thash __proto((void));
1747: STATIC thead_t *allocate_thead __proto((void));
1748: STATIC vlinks_t *allocate_vlinks __proto((void));
1749:
1750: STATIC void free_forward __proto((forward_t *));
1751: STATIC void free_scope __proto((scope_t *));
1752: STATIC void free_tag __proto((tag_t *));
1753: STATIC void free_thead __proto((thead_t *));
1754:
1.1.1.4 root 1755: STATIC char *local_index __proto((const char *, int));
1756: STATIC char *local_rindex __proto((const char *, int));
1757:
1.1.1.6 root 1758: #ifndef __alpha
1.1.1.3 root 1759: extern char *sbrk __proto((int));
1760: extern void free __proto((PTR_T));
1.1.1.6 root 1761: #endif
1.1.1.3 root 1762: extern char *mktemp __proto((char *));
1763: extern long strtol __proto((const char *, char **, int));
1.1 root 1764:
1765: extern char *optarg;
1766: extern int optind;
1767: extern int opterr;
1768: extern char *version_string;
1.1.1.7 root 1769: #ifndef NO_SYS_SIGLIST
1770: #ifndef DONT_DECLARE_SYS_SIGLIST
1.1 root 1771: extern char *sys_siglist[NSIG + 1];
1.1.1.7 root 1772: #endif
1773: #endif
1.1 root 1774:
1775: #ifndef SEEK_SET /* Symbolic constants for the "fseek" function: */
1776: #define SEEK_SET 0 /* Set file pointer to offset */
1777: #define SEEK_CUR 1 /* Set file pointer to its current value plus offset */
1778: #define SEEK_END 2 /* Set file pointer to the size of the file plus offset */
1779: #endif
1780:
1781:
1782: /* List of assembler pseudo ops and beginning sequences that need
1783: special actions. Someday, this should be a hash table, and such,
1784: but for now a linear list of names and calls to memcmp will
1785: do...... */
1786:
1787: typedef struct _pseudo_ops {
1.1.1.3 root 1788: const char *name; /* pseudo-op in ascii */
1.1 root 1789: int len; /* length of name to compare */
1790: void (*func) __proto((const char *)); /* function to handle line */
1791: } pseudo_ops_t;
1792:
1793: static pseudo_ops_t pseudo_ops[] = {
1794: { "#.def", sizeof("#.def")-1, parse_def },
1795: { "#.begin", sizeof("#.begin")-1, parse_begin },
1796: { "#.bend", sizeof("#.bend")-1, parse_bend },
1797: { ".end", sizeof(".end")-1, parse_end },
1798: { ".ent", sizeof(".ent")-1, parse_ent },
1799: { ".file", sizeof(".file")-1, parse_file },
1800: { "#.stabs", sizeof("#.stabs")-1, parse_stabs },
1801: { "#.stabn", sizeof("#.stabn")-1, parse_stabn },
1802: { ".stabs", sizeof(".stabs")-1, parse_stabs },
1803: { ".stabn", sizeof(".stabn")-1, parse_stabn },
1.1.1.2 root 1804: { "#@stabs", sizeof("#@stabs")-1, mark_stabs },
1.1 root 1805: };
1806:
1807:
1808: /* Add a page to a varray object. */
1809:
1810: STATIC void
1811: add_varray_page (vp)
1812: varray_t *vp; /* varray to add page to */
1813: {
1814: vlinks_t *new_links = allocate_vlinks ();
1815:
1816: #ifdef MALLOC_CHECK
1817: if (vp->object_size > 1)
1818: new_links->datum = (page_t *) xcalloc (1, vp->object_size);
1819: else
1820: #endif
1821: new_links->datum = allocate_page ();
1822:
1823: alloc_counts[ (int)alloc_type_varray ].total_alloc++;
1824: alloc_counts[ (int)alloc_type_varray ].total_pages++;
1825:
1826: new_links->start_index = vp->num_allocated;
1827: vp->objects_last_page = 0;
1828:
1829: if (vp->first == (vlinks_t *)0) /* first allocation? */
1830: vp->first = vp->last = new_links;
1831: else
1832: { /* 2nd or greater allocation */
1833: new_links->prev = vp->last;
1834: vp->last->next = new_links;
1835: vp->last = new_links;
1836: }
1837: }
1838:
1839:
1840: /* Compute hash code (from tree.c) */
1841:
1842: #define HASHBITS 30
1843:
1844: STATIC shash_t *
1845: hash_string (text, hash_len, hash_tbl, ret_hash_index)
1846: const char *text; /* ptr to text to hash */
1847: Ptrdiff_t hash_len; /* length of the text */
1848: shash_t **hash_tbl; /* hash table */
1849: symint_t *ret_hash_index; /* ptr to store hash index */
1850: {
1851: register unsigned long hi;
1852: register Ptrdiff_t i;
1853: register shash_t *ptr;
1854: register int first_ch = *text;
1855:
1856: hi = hash_len;
1857: for (i = 0; i < hash_len; i++)
1858: hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
1859:
1860: hi &= (1 << HASHBITS) - 1;
1861: hi %= SHASH_SIZE;
1862:
1863: if (ret_hash_index != (symint_t *)0)
1864: *ret_hash_index = hi;
1865:
1866: for (ptr = hash_tbl[hi]; ptr != (shash_t *)0; ptr = ptr->next)
1867: if (hash_len == ptr->len
1868: && first_ch == ptr->string[0]
1869: && memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
1870: break;
1871:
1872: return ptr;
1873: }
1874:
1875:
1876: /* Add a string (and null pad) to one of the string tables. A
1877: consequence of hashing strings, is that we don't let strings
1878: cross page boundaries. The extra nulls will be ignored. */
1879:
1880: STATIC symint_t
1881: add_string (vp, hash_tbl, start, end_p1, ret_hash)
1882: varray_t *vp; /* string virtual array */
1883: shash_t **hash_tbl; /* ptr to hash table */
1884: const char *start; /* 1st byte in string */
1885: const char *end_p1; /* 1st byte after string */
1886: shash_t **ret_hash; /* return hash pointer */
1887: {
1888: register Ptrdiff_t len = end_p1 - start;
1889: register shash_t *hash_ptr;
1890: symint_t hi;
1891:
1892: if (len >= PAGE_USIZE)
1893: fatal ("String too big (%ld bytes)", (long) len);
1894:
1895: hash_ptr = hash_string (start, len, hash_tbl, &hi);
1896: if (hash_ptr == (shash_t *)0)
1897: {
1898: register char *p;
1899:
1900: if (vp->objects_last_page + len >= PAGE_USIZE)
1901: {
1902: vp->num_allocated =
1903: ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
1904: add_varray_page (vp);
1905: }
1906:
1907: hash_ptr = allocate_shash ();
1908: hash_ptr->next = hash_tbl[hi];
1909: hash_tbl[hi] = hash_ptr;
1910:
1911: hash_ptr->len = len;
1.1.1.4 root 1912: hash_ptr->indx = vp->num_allocated;
1913: hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
1.1 root 1914:
1915: vp->objects_last_page += len+1;
1916: vp->num_allocated += len+1;
1917:
1918: while (len-- > 0)
1919: *p++ = *start++;
1920:
1921: *p = '\0';
1922: }
1923:
1924: if (ret_hash != (shash_t **)0)
1925: *ret_hash = hash_ptr;
1926:
1.1.1.4 root 1927: return hash_ptr->indx;
1.1 root 1928: }
1929:
1930:
1931: /* Add a local symbol. */
1932:
1933: STATIC symint_t
1934: add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
1935: const char *str_start; /* first byte in string */
1936: const char *str_end_p1; /* first byte after string */
1937: st_t type; /* symbol type */
1938: sc_t storage; /* storage class */
1939: symint_t value; /* value of symbol */
1940: symint_t indx; /* index to local/aux. syms */
1941: {
1942: register symint_t ret;
1943: register SYMR *psym;
1944: register scope_t *pscope;
1945: register thead_t *ptag_head;
1946: register tag_t *ptag;
1947: register tag_t *ptag_next;
1948: register varray_t *vp = &cur_file_ptr->symbols;
1949: register int scope_delta = 0;
1950: shash_t *hash_ptr = (shash_t *)0;
1951:
1952: if (vp->objects_last_page == vp->objects_per_page)
1953: add_varray_page (vp);
1954:
1955: psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
1956:
1957: psym->value = value;
1958: psym->st = (unsigned) type;
1959: psym->sc = (unsigned) storage;
1960: psym->index = indx;
1961: psym->iss = (str_start == (const char *)0)
1962: ? 0
1963: : add_string (&cur_file_ptr->strings,
1964: &cur_file_ptr->shash_head[0],
1965: str_start,
1966: str_end_p1,
1967: &hash_ptr);
1968:
1969: ret = vp->num_allocated++;
1970:
1971: if (MIPS_IS_STAB(psym))
1972: return ret;
1973:
1974: /* Save the symbol within the hash table if this is a static
1975: item, and it has a name. */
1976: if (hash_ptr != (shash_t *)0
1977: && (type == st_Global || type == st_Static || type == st_Label
1978: || type == st_Proc || type == st_StaticProc))
1979: hash_ptr->sym_ptr = psym;
1980:
1981: /* push or pop a scope if appropriate. */
1982: switch (type)
1983: {
1984: default:
1985: break;
1986:
1987: case st_File: /* beginning of file */
1988: case st_Proc: /* procedure */
1989: case st_StaticProc: /* static procedure */
1990: case st_Block: /* begin scope */
1991: pscope = allocate_scope ();
1992: pscope->prev = cur_file_ptr->cur_scope;
1993: pscope->lsym = psym;
1994: pscope->lnumber = ret;
1995: pscope->type = type;
1996: cur_file_ptr->cur_scope = pscope;
1997:
1998: if (type != st_File)
1999: scope_delta = 1;
2000:
2001: /* For every block type except file, struct, union, or
2002: enumeration blocks, push a level on the tag stack. We omit
2003: file types, so that tags can span file boundaries. */
2004: if (type != st_File && storage != sc_Info)
2005: {
2006: ptag_head = allocate_thead ();
2007: ptag_head->first_tag = 0;
2008: ptag_head->prev = cur_tag_head;
2009: cur_tag_head = ptag_head;
2010: }
2011: break;
2012:
2013: case st_End:
2014: pscope = cur_file_ptr->cur_scope;
2015: if (pscope == (scope_t *)0)
2016: error ("internal error, too many st_End's");
2017:
2018: else
2019: {
2020: st_t begin_type = (st_t) pscope->lsym->st;
2021:
2022: if (begin_type != st_File)
2023: scope_delta = -1;
2024:
2025: /* Except for file, structure, union, or enumeration end
2026: blocks remove all tags created within this scope. */
2027: if (begin_type != st_File && storage != sc_Info)
2028: {
2029: ptag_head = cur_tag_head;
2030: cur_tag_head = ptag_head->prev;
2031:
2032: for (ptag = ptag_head->first_tag;
2033: ptag != (tag_t *)0;
2034: ptag = ptag_next)
2035: {
2036: if (ptag->forward_ref != (forward_t *)0)
2037: add_unknown_tag (ptag);
2038:
2039: ptag_next = ptag->same_block;
2040: ptag->hash_ptr->tag_ptr = ptag->same_name;
2041: free_tag (ptag);
2042: }
2043:
2044: free_thead (ptag_head);
2045: }
2046:
2047: cur_file_ptr->cur_scope = pscope->prev;
2048: psym->index = pscope->lnumber; /* blk end gets begin sym # */
2049:
2050: if (storage != sc_Info)
2051: psym->iss = pscope->lsym->iss; /* blk end gets same name */
2052:
2053: if (begin_type == st_File || begin_type == st_Block)
1.1.1.4 root 2054: pscope->lsym->index = ret+1; /* block begin gets next sym # */
1.1 root 2055:
2056: /* Functions push two or more aux words as follows:
2057: 1st word: index+1 of the end symbol
2058: 2nd word: type of the function (plus any aux words needed).
2059: Also, tie the external pointer back to the function begin symbol. */
2060: else
2061: {
2062: symint_t type;
2063: pscope->lsym->index = add_aux_sym_symint (ret+1);
2064: type = add_aux_sym_tir (&last_func_type_info,
2065: hash_no,
2066: &cur_file_ptr->thash_head[0]);
2067: if (last_func_eptr)
2068: {
2069: last_func_eptr->ifd = cur_file_ptr->file_index;
1.1.1.6 root 2070:
2071: /* The index for an external st_Proc symbol is the index
2072: of the st_Proc symbol in the local symbol table. */
2073: last_func_eptr->asym.index = psym->index;
1.1 root 2074: }
2075: }
2076:
2077: free_scope (pscope);
2078: }
2079: }
2080:
2081: cur_file_ptr->nested_scopes += scope_delta;
2082:
2083: if (debug && type != st_File
2084: && (debug > 2 || type == st_Block || type == st_End
2085: || type == st_Proc || type == st_StaticProc))
2086: {
2087: char *sc_str = sc_to_string (storage);
2088: char *st_str = st_to_string (type);
2089: int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
2090:
2091: fprintf (stderr,
2092: "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
2093: value, depth, sc_str);
2094:
2095: if (str_start && str_end_p1 - str_start > 0)
2096: fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2097: else
2098: {
2099: Size_t len = strlen (st_str);
2100: fprintf (stderr, " st= %.*s\n", len-1, st_str);
2101: }
2102: }
2103:
2104: return ret;
2105: }
2106:
2107:
2108: /* Add an external symbol. */
2109:
2110: STATIC symint_t
2111: add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
2112: const char *str_start; /* first byte in string */
2113: const char *str_end_p1; /* first byte after string */
2114: st_t type; /* symbol type */
2115: sc_t storage; /* storage class */
2116: long value; /* value of symbol */
2117: symint_t indx; /* index to local/aux. syms */
2118: int ifd; /* file index */
2119: {
2120: register EXTR *psym;
2121: register varray_t *vp = &ext_symbols;
2122: shash_t *hash_ptr = (shash_t *)0;
2123:
2124: if (debug > 1)
2125: {
2126: char *sc_str = sc_to_string (storage);
2127: char *st_str = st_to_string (type);
2128:
2129: fprintf (stderr,
2130: "\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
2131: value, ifd, sc_str);
2132:
2133: if (str_start && str_end_p1 - str_start > 0)
2134: fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
2135: else
2136: fprintf (stderr, " st= %s\n", st_str);
2137: }
2138:
2139: if (vp->objects_last_page == vp->objects_per_page)
2140: add_varray_page (vp);
2141:
2142: psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
2143:
2144: psym->ifd = ifd;
2145: psym->asym.value = value;
2146: psym->asym.st = (unsigned) type;
2147: psym->asym.sc = (unsigned) storage;
2148: psym->asym.index = indx;
2149: psym->asym.iss = (str_start == (const char *)0)
2150: ? 0
2151: : add_string (&ext_strings,
2152: &ext_str_hash[0],
2153: str_start,
2154: str_end_p1,
2155: &hash_ptr);
2156:
2157: hash_ptr->esym_ptr = psym;
2158: return vp->num_allocated++;
2159: }
2160:
2161:
2162: /* Add an auxiliary symbol (passing a symint). */
2163:
2164: STATIC symint_t
2165: add_aux_sym_symint (aux_word)
1.1.1.3 root 2166: symint_t aux_word; /* auxiliary information word */
1.1 root 2167: {
2168: register AUXU *aux_ptr;
2169: register efdr_t *file_ptr = cur_file_ptr;
2170: register varray_t *vp = &file_ptr->aux_syms;
2171:
2172: if (vp->objects_last_page == vp->objects_per_page)
2173: add_varray_page (vp);
2174:
2175: aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2176: aux_ptr->isym = aux_word;
2177:
2178: return vp->num_allocated++;
2179: }
2180:
2181:
2182: /* Add an auxiliary symbol (passing a file/symbol index combo). */
2183:
2184: STATIC symint_t
2185: add_aux_sym_rndx (file_index, sym_index)
2186: int file_index;
2187: symint_t sym_index;
2188: {
2189: register AUXU *aux_ptr;
2190: register efdr_t *file_ptr = cur_file_ptr;
2191: register varray_t *vp = &file_ptr->aux_syms;
2192:
2193: if (vp->objects_last_page == vp->objects_per_page)
2194: add_varray_page (vp);
2195:
2196: aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2197: aux_ptr->rndx.rfd = file_index;
2198: aux_ptr->rndx.index = sym_index;
2199:
2200: return vp->num_allocated++;
2201: }
2202:
2203:
2204: /* Add an auxiliary symbol (passing the basic type and possibly
2205: type qualifiers). */
2206:
2207: STATIC symint_t
2208: add_aux_sym_tir (t, state, hash_tbl)
2209: type_info_t *t; /* current type information */
2210: hash_state_t state; /* whether to hash type or not */
2211: thash_t **hash_tbl; /* pointer to hash table to use */
2212: {
2213: register AUXU *aux_ptr;
2214: register efdr_t *file_ptr = cur_file_ptr;
2215: register varray_t *vp = &file_ptr->aux_syms;
2216: static AUXU init_aux;
2217: symint_t ret;
2218: int i;
2219: AUXU aux;
2220:
2221: aux = init_aux;
2222: aux.ti.bt = (int) t->basic_type;
2223: aux.ti.continued = 0;
2224: aux.ti.fBitfield = t->bitfield;
2225:
2226: aux.ti.tq0 = (int) t->type_qualifiers[0];
2227: aux.ti.tq1 = (int) t->type_qualifiers[1];
2228: aux.ti.tq2 = (int) t->type_qualifiers[2];
2229: aux.ti.tq3 = (int) t->type_qualifiers[3];
2230: aux.ti.tq4 = (int) t->type_qualifiers[4];
2231: aux.ti.tq5 = (int) t->type_qualifiers[5];
2232:
2233:
2234: /* For anything that adds additional information, we must not hash,
2235: so check here, and reset our state. */
2236:
2237: if (state != hash_no
2238: && (t->type_qualifiers[0] == tq_Array
2239: || t->type_qualifiers[1] == tq_Array
2240: || t->type_qualifiers[2] == tq_Array
2241: || t->type_qualifiers[3] == tq_Array
2242: || t->type_qualifiers[4] == tq_Array
2243: || t->type_qualifiers[5] == tq_Array
2244: || t->basic_type == bt_Struct
2245: || t->basic_type == bt_Union
2246: || t->basic_type == bt_Enum
2247: || t->bitfield
2248: || t->num_dims > 0))
2249: state = hash_no;
2250:
2251: /* See if we can hash this type, and save some space, but some types
2252: can't be hashed (because they contain arrays or continuations),
2253: and others can be put into the hash list, but cannot use existing
2254: types because other aux entries precede this one. */
2255:
2256: if (state != hash_no)
2257: {
2258: register thash_t *hash_ptr;
2259: register symint_t hi;
2260:
2261: hi = aux.isym & ((1 << HASHBITS) - 1);
2262: hi %= THASH_SIZE;
2263:
2264: for (hash_ptr = hash_tbl[hi];
2265: hash_ptr != (thash_t *)0;
2266: hash_ptr = hash_ptr->next)
2267: {
2268: if (aux.isym == hash_ptr->type.isym)
2269: break;
2270: }
2271:
2272: if (hash_ptr != (thash_t *)0 && state == hash_yes)
1.1.1.4 root 2273: return hash_ptr->indx;
1.1 root 2274:
2275: if (hash_ptr == (thash_t *)0)
2276: {
2277: hash_ptr = allocate_thash ();
2278: hash_ptr->next = hash_tbl[hi];
2279: hash_ptr->type = aux;
1.1.1.4 root 2280: hash_ptr->indx = vp->num_allocated;
1.1 root 2281: hash_tbl[hi] = hash_ptr;
2282: }
2283: }
2284:
2285: /* Everything is set up, add the aux symbol. */
2286: if (vp->objects_last_page == vp->objects_per_page)
2287: add_varray_page (vp);
2288:
2289: aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
2290: *aux_ptr = aux;
2291:
2292: ret = vp->num_allocated++;
2293:
2294: /* Add bitfield length if it exists.
2295:
2296: NOTE: Mips documentation claims bitfield goes at the end of the
2297: AUX record, but the DECstation compiler emits it here.
2298: (This would only make a difference for enum bitfields.)
2299:
2300: Also note: We use the last size given since gcc may emit 2
2301: for an enum bitfield. */
2302:
2303: if (t->bitfield)
2304: (void) add_aux_sym_symint ((symint_t)t->sizes[t->num_sizes-1]);
2305:
2306:
2307: /* Add tag information if needed. Structure, union, and enum
2308: references add 2 aux symbols: a [file index, symbol index]
2309: pointer to the structure type, and the current file index. */
2310:
2311: if (t->basic_type == bt_Struct
2312: || t->basic_type == bt_Union
2313: || t->basic_type == bt_Enum)
2314: {
2315: register symint_t file_index = t->tag_ptr->ifd;
1.1.1.4 root 2316: register symint_t sym_index = t->tag_ptr->indx;
1.1 root 2317:
2318: if (t->unknown_tag)
2319: {
2320: (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2321: (void) add_aux_sym_symint ((symint_t)-1);
2322: }
2323: else if (sym_index != indexNil)
2324: {
2325: (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2326: (void) add_aux_sym_symint (file_index);
2327: }
2328: else
2329: {
2330: register forward_t *forward_ref = allocate_forward ();
2331:
2332: forward_ref->type_ptr = aux_ptr;
2333: forward_ref->next = t->tag_ptr->forward_ref;
2334: t->tag_ptr->forward_ref = forward_ref;
2335:
2336: (void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
2337: forward_ref->index_ptr
2338: = &vp->last->datum->aux[ vp->objects_last_page - 1];
2339:
2340: (void) add_aux_sym_symint (file_index);
2341: forward_ref->ifd_ptr
2342: = &vp->last->datum->aux[ vp->objects_last_page - 1];
2343: }
2344: }
2345:
2346: /* Add information about array bounds if they exist. */
2347: for (i = 0; i < t->num_dims; i++)
2348: {
2349: (void) add_aux_sym_rndx (ST_RFDESCAPE,
2350: cur_file_ptr->int_type);
2351:
2352: (void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/
2353: (void) add_aux_sym_symint ((symint_t)0); /* low bound */
2354: (void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/
2355: (void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */
2356: ? 0
2357: : (t->sizes[i] * 8) / t->dimensions[i]);
2358: };
2359:
1.1.1.8 ! root 2360: /* NOTE: Mips documentation claims that the bitfield width goes here.
1.1 root 2361: But it needs to be emitted earlier. */
2362:
2363: return ret;
2364: }
2365:
2366:
2367: /* Add a tag to the tag table (unless it already exists). */
2368:
2369: STATIC tag_t *
1.1.1.4 root 2370: get_tag (tag_start, tag_end_p1, indx, basic_type)
1.1 root 2371: const char *tag_start; /* 1st byte of tag name */
2372: const char *tag_end_p1; /* 1st byte after tag name */
1.1.1.4 root 2373: symint_t indx; /* index of tag start block */
1.1 root 2374: bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
2375: {
2376: shash_t *hash_ptr;
2377: tag_t *tag_ptr;
2378: hash_ptr = hash_string (tag_start,
2379: tag_end_p1 - tag_start,
2380: &tag_hash[0],
2381: (symint_t *)0);
2382:
2383: if (hash_ptr != (shash_t *)0
2384: && hash_ptr->tag_ptr != (tag_t *)0)
2385: {
2386: tag_ptr = hash_ptr->tag_ptr;
1.1.1.4 root 2387: if (indx != indexNil)
1.1 root 2388: {
2389: tag_ptr->basic_type = basic_type;
2390: tag_ptr->ifd = cur_file_ptr->file_index;
1.1.1.4 root 2391: tag_ptr->indx = indx;
1.1 root 2392: }
2393: return tag_ptr;
2394: }
2395:
2396: (void) add_string (&tag_strings,
2397: &tag_hash[0],
2398: tag_start,
2399: tag_end_p1,
2400: &hash_ptr);
2401:
2402: tag_ptr = allocate_tag ();
2403: tag_ptr->forward_ref = (forward_t *) 0;
2404: tag_ptr->hash_ptr = hash_ptr;
2405: tag_ptr->same_name = hash_ptr->tag_ptr;
2406: tag_ptr->basic_type = basic_type;
1.1.1.4 root 2407: tag_ptr->indx = indx;
2408: tag_ptr->ifd = (indx == indexNil) ? -1 : cur_file_ptr->file_index;
1.1 root 2409: tag_ptr->same_block = cur_tag_head->first_tag;
2410:
2411: cur_tag_head->first_tag = tag_ptr;
2412: hash_ptr->tag_ptr = tag_ptr;
2413:
2414: return tag_ptr;
2415: }
2416:
2417:
2418: /* Add an unknown {struct, union, enum} tag. */
2419:
2420: STATIC void
2421: add_unknown_tag (ptag)
2422: tag_t *ptag; /* pointer to tag information */
2423: {
2424: shash_t *hash_ptr = ptag->hash_ptr;
2425: char *name_start = hash_ptr->string;
2426: char *name_end_p1 = name_start + hash_ptr->len;
2427: forward_t *f_next = ptag->forward_ref;
2428: forward_t *f_cur;
2429: int sym_index;
2430: int file_index = cur_file_ptr->file_index;
2431:
2432: if (debug > 1)
2433: {
2434: char *agg_type = "{unknown aggregate type}";
2435: switch (ptag->basic_type)
2436: {
2437: case bt_Struct: agg_type = "struct"; break;
2438: case bt_Union: agg_type = "union"; break;
2439: case bt_Enum: agg_type = "enum"; break;
2440: default: break;
2441: }
2442:
2443: fprintf (stderr, "unknown %s %.*s found\n", agg_type,
2444: hash_ptr->len, name_start);
2445: }
2446:
2447: sym_index = add_local_symbol (name_start,
2448: name_end_p1,
2449: st_Block,
2450: sc_Info,
2451: (symint_t)0,
2452: (symint_t)0);
2453:
2454: (void) add_local_symbol (name_start,
2455: name_end_p1,
2456: st_End,
2457: sc_Info,
2458: (symint_t)0,
2459: (symint_t)0);
2460:
2461: while (f_next != (forward_t *)0)
2462: {
2463: f_cur = f_next;
2464: f_next = f_next->next;
2465:
2466: f_cur->ifd_ptr->isym = file_index;
2467: f_cur->index_ptr->rndx.index = sym_index;
2468:
2469: free_forward (f_cur);
2470: }
2471:
2472: return;
2473: }
2474:
2475:
2476: /* Add a procedure to the current file's list of procedures, and record
2477: this is the current procedure. If the assembler created a PDR for
2478: this procedure, use that to initialize the current PDR. */
2479:
2480: STATIC void
2481: add_procedure (func_start, func_end_p1)
2482: const char *func_start; /* 1st byte of func name */
2483: const char *func_end_p1; /* 1st byte after func name */
2484: {
2485: register PDR *new_proc_ptr;
2486: register efdr_t *file_ptr = cur_file_ptr;
2487: register varray_t *vp = &file_ptr->procs;
2488: register symint_t value = 0;
2489: register st_t proc_type = st_Proc;
2490: register shash_t *shash_ptr = hash_string (func_start,
2491: func_end_p1 - func_start,
2492: &orig_str_hash[0],
2493: (symint_t *)0);
2494:
2495: if (debug)
2496: fputc ('\n', stderr);
2497:
2498: if (vp->objects_last_page == vp->objects_per_page)
2499: add_varray_page (vp);
2500:
2501: cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
2502:
2503: vp->num_allocated++;
2504:
2505:
2506: /* Did the assembler create this procedure? If so, get the PDR information. */
2507: cur_oproc_ptr = (PDR *)0;
2508: if (shash_ptr != (shash_t *)0)
2509: {
2510: register PDR *old_proc_ptr = shash_ptr->proc_ptr;
2511: register SYMR *sym_ptr = shash_ptr->sym_ptr;
2512:
2513: if (old_proc_ptr != (PDR *)0
2514: && sym_ptr != (SYMR *)0
2515: && ((st_t)sym_ptr->st == st_Proc || (st_t)sym_ptr->st == st_StaticProc))
2516: {
2517: cur_oproc_begin = sym_ptr;
2518: cur_oproc_end = shash_ptr->end_ptr;
2519: value = sym_ptr->value;
2520:
2521: cur_oproc_ptr = old_proc_ptr;
2522: proc_type = (st_t)sym_ptr->st;
2523: *new_proc_ptr = *old_proc_ptr; /* initialize */
2524: }
2525: }
2526:
2527: if (cur_oproc_ptr == (PDR *)0)
2528: error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
2529:
2530: /* Determine the start of symbols. */
2531: new_proc_ptr->isym = file_ptr->symbols.num_allocated;
2532:
2533: /* Push the start of the function. */
2534: (void) add_local_symbol (func_start, func_end_p1,
2535: proc_type, sc_Text,
2536: value,
2537: (symint_t)0);
2538: }
2539:
2540:
2541: /* Add a new filename, and set up all of the file relative
2542: virtual arrays (strings, symbols, aux syms, etc.). Record
2543: where the current file structure lives. */
2544:
2545: STATIC void
2546: add_file (file_start, file_end_p1)
2547: const char *file_start; /* first byte in string */
2548: const char *file_end_p1; /* first byte after string */
2549: {
2550: static char zero_bytes[2] = { '\0', '\0' };
2551:
2552: register Ptrdiff_t len = file_end_p1 - file_start;
2553: register int first_ch = *file_start;
2554: register efdr_t *file_ptr;
2555:
2556: if (debug)
2557: fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
2558:
2559: /* See if the file has already been created. */
2560: for (file_ptr = first_file;
2561: file_ptr != (efdr_t *)0;
2562: file_ptr = file_ptr->next_file)
2563: {
2564: if (first_ch == file_ptr->name[0]
2565: && file_ptr->name[len] == '\0'
2566: && memcmp ((CPTR_T) file_start, (CPTR_T) file_ptr->name, len) == 0)
2567: {
2568: cur_file_ptr = file_ptr;
2569: break;
2570: }
2571: }
2572:
2573: /* If this is a new file, create it. */
2574: if (file_ptr == (efdr_t *)0)
2575: {
2576: if (file_desc.objects_last_page == file_desc.objects_per_page)
2577: add_varray_page (&file_desc);
2578:
2579: file_ptr = cur_file_ptr =
2580: &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
2581: *file_ptr = init_file;
2582:
2583: file_ptr->file_index = file_desc.num_allocated++;
2584:
2585: /* Allocate the string hash table. */
2586: file_ptr->shash_head = (shash_t **) allocate_page ();
2587:
2588: /* Make sure 0 byte in string table is null */
2589: add_string (&file_ptr->strings,
2590: &file_ptr->shash_head[0],
2591: &zero_bytes[0],
2592: &zero_bytes[0],
2593: (shash_t **)0);
2594:
2595: if (file_end_p1 - file_start > PAGE_USIZE-2)
2596: fatal ("Filename goes over one page boundary.");
2597:
2598: /* Push the start of the filename. We assume that the filename
2599: will be stored at string offset 1. */
2600: (void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
2601: (symint_t)0, (symint_t)0);
2602: file_ptr->fdr.rss = 1;
2603: file_ptr->name = &file_ptr->strings.last->datum->byte[1];
2604: file_ptr->name_len = file_end_p1 - file_start;
2605:
2606: /* Update the linked list of file descriptors. */
2607: *last_file_ptr = file_ptr;
2608: last_file_ptr = &file_ptr->next_file;
2609:
2610: /* Add void & int types to the file (void should be first to catch
2611: errant 0's within the index fields). */
2612: file_ptr->void_type = add_aux_sym_tir (&void_type_info,
2613: hash_yes,
2614: &cur_file_ptr->thash_head[0]);
2615:
2616: file_ptr->int_type = add_aux_sym_tir (&int_type_info,
2617: hash_yes,
2618: &cur_file_ptr->thash_head[0]);
2619: }
2620: }
2621:
2622:
2623: /* Add a stream of random bytes to a varray. */
2624:
2625: STATIC void
2626: add_bytes (vp, input_ptr, nitems)
2627: varray_t *vp; /* virtual array to add too */
2628: char *input_ptr; /* start of the bytes */
2629: Size_t nitems; /* # items to move */
2630: {
2631: register Size_t move_items;
2632: register Size_t move_bytes;
2633: register char *ptr;
2634:
2635: while (nitems > 0)
2636: {
2637: if (vp->objects_last_page >= vp->objects_per_page)
2638: add_varray_page (vp);
2639:
2640: ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
2641: move_items = vp->objects_per_page - vp->objects_last_page;
2642: if (move_items > nitems)
2643: move_items = nitems;
2644:
2645: move_bytes = move_items * vp->object_size;
2646: nitems -= move_items;
2647:
2648: if (move_bytes >= 32)
2649: {
2650: (void) memcpy ((PTR_T) ptr, (CPTR_T) input_ptr, move_bytes);
2651: input_ptr += move_bytes;
2652: }
2653: else
2654: {
2655: while (move_bytes-- > 0)
2656: *ptr++ = *input_ptr++;
2657: }
2658: }
2659: }
2660:
2661:
2662: /* Convert storage class to string. */
2663:
2664: STATIC char *
2665: sc_to_string(storage_class)
2666: sc_t storage_class;
2667: {
2668: switch(storage_class)
2669: {
2670: case sc_Nil: return "Nil,";
2671: case sc_Text: return "Text,";
2672: case sc_Data: return "Data,";
2673: case sc_Bss: return "Bss,";
2674: case sc_Register: return "Register,";
2675: case sc_Abs: return "Abs,";
2676: case sc_Undefined: return "Undefined,";
2677: case sc_CdbLocal: return "CdbLocal,";
2678: case sc_Bits: return "Bits,";
2679: case sc_CdbSystem: return "CdbSystem,";
2680: case sc_RegImage: return "RegImage,";
2681: case sc_Info: return "Info,";
2682: case sc_UserStruct: return "UserStruct,";
2683: case sc_SData: return "SData,";
2684: case sc_SBss: return "SBss,";
2685: case sc_RData: return "RData,";
2686: case sc_Var: return "Var,";
2687: case sc_Common: return "Common,";
2688: case sc_SCommon: return "SCommon,";
2689: case sc_VarRegister: return "VarRegister,";
2690: case sc_Variant: return "Variant,";
2691: case sc_SUndefined: return "SUndefined,";
2692: case sc_Init: return "Init,";
2693: case sc_Max: return "Max,";
2694: }
2695:
2696: return "???,";
2697: }
2698:
2699:
2700: /* Convert symbol type to string. */
2701:
2702: STATIC char *
2703: st_to_string(symbol_type)
2704: st_t symbol_type;
2705: {
2706: switch(symbol_type)
2707: {
2708: case st_Nil: return "Nil,";
2709: case st_Global: return "Global,";
2710: case st_Static: return "Static,";
2711: case st_Param: return "Param,";
2712: case st_Local: return "Local,";
2713: case st_Label: return "Label,";
2714: case st_Proc: return "Proc,";
2715: case st_Block: return "Block,";
2716: case st_End: return "End,";
2717: case st_Member: return "Member,";
2718: case st_Typedef: return "Typedef,";
2719: case st_File: return "File,";
2720: case st_RegReloc: return "RegReloc,";
2721: case st_Forward: return "Forward,";
2722: case st_StaticProc: return "StaticProc,";
2723: case st_Constant: return "Constant,";
2724: case st_Str: return "String,";
2725: case st_Number: return "Number,";
2726: case st_Expr: return "Expr,";
2727: case st_Type: return "Type,";
2728: case st_Max: return "Max,";
2729: }
2730:
2731: return "???,";
2732: }
2733:
2734:
1.1.1.3 root 2735: /* Read a line from standard input, and return the start of the buffer
2736: (which is grows if the line is too big). We split lines at the
1.1.1.4 root 2737: semi-colon, and return each logical line independently. */
1.1 root 2738:
2739: STATIC char *
2740: read_line __proto((void))
2741: {
1.1.1.3 root 2742: static int line_split_p = 0;
2743: register int string_p = 0;
2744: register int comment_p = 0;
1.1 root 2745: register int ch;
2746: register char *ptr;
2747:
2748: if (cur_line_start == (char *)0)
2749: { /* allocate initial page */
2750: cur_line_start = (char *) allocate_page ();
2751: cur_line_alloc = PAGE_SIZE;
2752: }
2753:
1.1.1.3 root 2754: if (!line_split_p)
2755: line_number++;
2756:
2757: line_split_p = 0;
1.1 root 2758: cur_line_nbytes = 0;
2759:
2760: for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
2761: {
2762: if (++cur_line_nbytes >= cur_line_alloc-1)
2763: {
2764: register int num_pages = cur_line_alloc / PAGE_SIZE;
2765: register char *old_buffer = cur_line_start;
2766:
2767: cur_line_alloc += PAGE_SIZE;
2768: cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
2769: memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
2770:
2771: ptr = cur_line_start + cur_line_nbytes - 1;
2772: }
2773:
2774: if (ch == '\n')
2775: {
2776: *ptr++ = '\n';
2777: *ptr = '\0';
2778: cur_line_ptr = cur_line_start;
2779: return cur_line_ptr;
2780: }
1.1.1.3 root 2781:
2782: else if (ch == '\0')
2783: error ("Null character found in input");
2784:
2785: else if (!comment_p)
2786: {
2787: if (ch == '"')
2788: string_p = !string_p;
2789:
2790: else if (ch == '#')
2791: comment_p++;
2792:
1.1.1.4 root 2793: else if (ch == ';' && !string_p)
1.1.1.3 root 2794: {
2795: line_split_p = 1;
2796: *ptr++ = '\n';
2797: *ptr = '\0';
2798: cur_line_ptr = cur_line_start;
2799: return cur_line_ptr;
2800: }
2801: }
1.1 root 2802: }
2803:
2804: if (ferror (stdin))
2805: pfatal_with_name (input_name);
2806:
2807: cur_line_ptr = (char *)0;
2808: return (char *)0;
2809: }
2810:
2811:
2812: /* Parse #.begin directives which have a label as the first argument
2813: which gives the location of the start of the block. */
2814:
2815: STATIC void
2816: parse_begin (start)
2817: const char *start; /* start of directive */
2818: {
2819: const char *end_p1; /* end of label */
2820: int ch;
2821: shash_t *hash_ptr; /* hash pointer to lookup label */
2822:
2823: if (cur_file_ptr == (efdr_t *)0)
2824: {
1.1.1.2 root 2825: error ("#.begin directive without a preceding .file directive");
1.1 root 2826: return;
2827: }
2828:
2829: if (cur_proc_ptr == (PDR *)0)
2830: {
1.1.1.2 root 2831: error ("#.begin directive without a preceding .ent directive");
1.1 root 2832: return;
2833: }
2834:
2835: for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2836: ;
2837:
2838: hash_ptr = hash_string (start,
2839: end_p1 - start,
2840: &orig_str_hash[0],
2841: (symint_t *)0);
2842:
2843: if (hash_ptr == (shash_t *)0)
2844: {
2845: error ("Label %.*s not found for #.begin", end_p1 - start, start);
2846: return;
2847: }
2848:
2849: if (cur_oproc_begin == (SYMR *)0)
2850: {
2851: error ("Procedure table %.*s not found for #.begin", end_p1 - start, start);
2852: return;
2853: }
2854:
2855: (void) add_local_symbol ((const char *)0, (const char *)0,
2856: st_Block, sc_Text,
2857: (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2858: (symint_t)0);
2859: }
2860:
2861:
2862: /* Parse #.bend directives which have a label as the first argument
2863: which gives the location of the end of the block. */
2864:
2865: STATIC void
2866: parse_bend (start)
2867: const char *start; /* start of directive */
2868: {
2869: const char *end_p1; /* end of label */
2870: int ch;
2871: shash_t *hash_ptr; /* hash pointer to lookup label */
2872:
2873: if (cur_file_ptr == (efdr_t *)0)
2874: {
1.1.1.2 root 2875: error ("#.begin directive without a preceding .file directive");
1.1 root 2876: return;
2877: }
2878:
2879: if (cur_proc_ptr == (PDR *)0)
2880: {
1.1.1.2 root 2881: error ("#.bend directive without a preceding .ent directive");
1.1 root 2882: return;
2883: }
2884:
2885: for (end_p1 = start; (ch = *end_p1) != '\0' && !isspace (ch); end_p1++)
2886: ;
2887:
2888: hash_ptr = hash_string (start,
2889: end_p1 - start,
2890: &orig_str_hash[0],
2891: (symint_t *)0);
2892:
2893: if (hash_ptr == (shash_t *)0)
2894: {
2895: error ("Label %.*s not found for #.bend", end_p1 - start, start);
2896: return;
2897: }
2898:
2899: if (cur_oproc_begin == (SYMR *)0)
2900: {
2901: error ("Procedure table %.*s not found for #.bend", end_p1 - start, start);
2902: return;
2903: }
2904:
2905: (void) add_local_symbol ((const char *)0, (const char *)0,
2906: st_End, sc_Text,
2907: (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
2908: (symint_t)0);
2909: }
2910:
2911:
2912: /* Parse #.def directives, which are contain standard COFF subdirectives
2913: to describe the debugging format. These subdirectives include:
2914:
2915: .scl specify storage class
2916: .val specify a value
2917: .endef specify end of COFF directives
2918: .type specify the type
2919: .size specify the size of an array
2920: .dim specify an array dimension
2921: .tag specify a tag for a struct, union, or enum. */
2922:
2923: STATIC void
2924: parse_def (name_start)
2925: const char *name_start; /* start of directive */
2926: {
2927: const char *dir_start; /* start of current directive*/
2928: const char *dir_end_p1; /* end+1 of current directive*/
2929: const char *arg_start; /* start of current argument */
2930: const char *arg_end_p1; /* end+1 of current argument */
2931: const char *name_end_p1; /* end+1 of label */
2932: const char *tag_start = (const char *)0; /* start of tag name */
2933: const char *tag_end_p1 = (const char *)0; /* end+1 of tag name */
2934: sc_t storage_class = sc_Nil;
2935: st_t symbol_type = st_Nil;
2936: type_info_t t;
2937: EXTR *eptr = (EXTR *)0; /* ext. sym equivalent to def*/
2938: int is_function = 0; /* != 0 if function */
2939: symint_t value = 0;
1.1.1.4 root 2940: symint_t indx = cur_file_ptr->void_type;
1.1 root 2941: int error_line = 0;
2942: symint_t arg_number;
2943: symint_t temp_array[ N_TQ ];
2944: int arg_was_number;
2945: int ch, i;
2946: Ptrdiff_t len;
2947:
2948: static int inside_enumeration = 0; /* is this an enumeration? */
2949:
2950:
2951: /* Initialize the type information. */
2952: t = type_info_init;
2953:
2954:
2955: /* Search for the end of the name being defined. */
1.1.1.4 root 2956: /* Allow spaces and such in names for G++ templates, which produce stabs
2957: that look like:
2958:
2959: #.def SMANIP<long unsigned int>; .scl 10; .type 0x8; .size 8; .endef */
2960:
2961: for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
2962: ;
2963:
2964: if (ch == '\0')
1.1 root 2965: {
1.1.1.4 root 2966: error_line = __LINE__;
2967: saber_stop ();
2968: goto bomb_out;
1.1 root 2969: }
2970:
2971: /* Parse the remaining subdirectives now. */
2972: dir_start = name_end_p1+1;
2973: for (;;)
2974: {
2975: while ((ch = *dir_start) == ' ' || ch == '\t')
2976: ++dir_start;
2977:
2978: if (ch != '.')
2979: {
2980: error_line = __LINE__;
2981: saber_stop ();
2982: goto bomb_out;
2983: }
2984:
2985: /* Are we done? */
2986: if (dir_start[1] == 'e'
2987: && memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
2988: break;
2989:
2990: /* Pick up the subdirective now */
2991: for (dir_end_p1 = dir_start+1;
2992: (ch = *dir_end_p1) != ' ' && ch != '\t';
2993: dir_end_p1++)
2994: {
2995: if (ch == '\0' || isspace (ch))
2996: {
2997: error_line = __LINE__;
2998: saber_stop ();
2999: goto bomb_out;
3000: }
3001: }
3002:
3003: /* Pick up the subdirective argument now. */
3004: arg_was_number = arg_number = 0;
3005: arg_end_p1 = (const char *)0;
3006: arg_start = dir_end_p1+1;
3007: ch = *arg_start;
3008: while (ch == ' ' || ch == '\t')
3009: ch = *++arg_start;
3010:
3011: if (isdigit (ch) || ch == '-' || ch == '+')
3012: {
3013: int ch2;
3014: arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
3015: if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3016: arg_was_number++;
3017: }
3018:
3019: else if (ch == '\0' || isspace (ch))
3020: {
3021: error_line = __LINE__;
3022: saber_stop ();
3023: goto bomb_out;
3024: }
3025:
3026: if (!arg_was_number)
1.1.1.4 root 3027: {
3028: /* Allow spaces and such in names for G++ templates. */
3029: for (arg_end_p1 = arg_start+1;
3030: (ch = *arg_end_p1) != ';' && ch != '\0';
3031: arg_end_p1++)
3032: ;
1.1 root 3033:
1.1.1.4 root 3034: if (ch == '\0')
3035: {
3036: error_line = __LINE__;
3037: saber_stop ();
3038: goto bomb_out;
3039: }
3040: }
1.1 root 3041:
3042: /* Classify the directives now. */
3043: len = dir_end_p1 - dir_start;
3044: switch (dir_start[1])
3045: {
3046: default:
3047: error_line = __LINE__;
3048: saber_stop ();
3049: goto bomb_out;
3050:
3051: case 'd':
3052: if (len == sizeof (".dim")-1
3053: && memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
3054: && arg_was_number)
3055: {
3056: symint_t *t_ptr = &temp_array[ N_TQ-1 ];
3057:
3058: *t_ptr = arg_number;
3059: while (*arg_end_p1 == ',' && arg_was_number)
3060: {
3061: arg_start = arg_end_p1+1;
3062: ch = *arg_start;
3063: while (ch == ' ' || ch == '\t')
3064: ch = *++arg_start;
3065:
3066: arg_was_number = 0;
3067: if (isdigit (ch) || ch == '-' || ch == '+')
3068: {
3069: int ch2;
3070: arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
3071: if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3072: arg_was_number++;
3073:
3074: if (t_ptr == &temp_array[0])
3075: {
3076: error_line = __LINE__;
3077: saber_stop ();
3078: goto bomb_out;
3079: }
3080:
3081: *--t_ptr = arg_number;
3082: }
3083: }
3084:
3085: /* Reverse order of dimensions. */
3086: while (t_ptr <= &temp_array[ N_TQ-1 ])
3087: {
3088: if (t.num_dims >= N_TQ-1)
3089: {
3090: error_line = __LINE__;
3091: saber_stop ();
3092: goto bomb_out;
3093: }
3094:
3095: t.dimensions[ t.num_dims++ ] = *t_ptr++;
3096: }
3097: break;
3098: }
3099: else
3100: {
3101: error_line = __LINE__;
3102: saber_stop ();
3103: goto bomb_out;
3104: }
3105:
3106:
3107: case 's':
3108: if (len == sizeof (".scl")-1
3109: && memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
3110: && arg_was_number
3111: && arg_number < ((symint_t) C_MAX))
3112: {
3113: /* If the symbol is a static or external, we have
3114: already gotten the appropriate type and class, so
3115: make sure we don't override those values. This is
3116: needed because there are some type and classes that
3117: are not in COFF, such as short data, etc. */
3118: if (symbol_type == st_Nil)
3119: {
3120: symbol_type = map_coff_sym_type[arg_number];
3121: storage_class = map_coff_storage [arg_number];
3122: }
3123: break;
3124: }
3125:
3126: else if (len == sizeof (".size")-1
3127: && memcmp (dir_start, ".size", sizeof (".size")-1) == 0
3128: && arg_was_number)
3129: {
3130: symint_t *t_ptr = &temp_array[ N_TQ-1 ];
3131:
3132: *t_ptr = arg_number;
3133: while (*arg_end_p1 == ',' && arg_was_number)
3134: {
3135: arg_start = arg_end_p1+1;
3136: ch = *arg_start;
3137: while (ch == ' ' || ch == '\t')
3138: ch = *++arg_start;
3139:
3140: arg_was_number = 0;
3141: if (isdigit (ch) || ch == '-' || ch == '+')
3142: {
3143: int ch2;
3144: arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
3145: if (arg_end_p1 != arg_start || (ch2 = *arg_end_p1 != ';') || ch2 != ',')
3146: arg_was_number++;
3147:
3148: if (t_ptr == &temp_array[0])
3149: {
3150: error_line = __LINE__;
3151: saber_stop ();
3152: goto bomb_out;
3153: }
3154:
3155: *--t_ptr = arg_number;
3156: }
3157: }
3158:
3159: /* Reverse order of sizes. */
3160: while (t_ptr <= &temp_array[ N_TQ-1 ])
3161: {
3162: if (t.num_sizes >= N_TQ-1)
3163: {
3164: error_line = __LINE__;
3165: saber_stop ();
3166: goto bomb_out;
3167: }
3168:
3169: t.sizes[ t.num_sizes++ ] = *t_ptr++;
3170: }
3171: break;
3172: }
3173:
3174: else
3175: {
3176: error_line = __LINE__;
3177: saber_stop ();
3178: goto bomb_out;
3179: }
3180:
3181:
3182: case 't':
3183: if (len == sizeof (".type")-1
3184: && memcmp (dir_start, ".type", sizeof (".type")-1) == 0
3185: && arg_was_number)
3186: {
3187: tq_t *tq_ptr = &t.type_qualifiers[0];
3188:
3189: t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
3190: t.basic_type = map_coff_types [(int)t.orig_type];
3191: for (i = N_TQ-1; i >= 0; i--)
3192: {
3193: int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
3194: & N_TMASK);
3195:
3196: if (dt != (int)DT_NON)
3197: *tq_ptr++ = map_coff_derived_type [dt];
3198: }
3199:
3200: /* If this is a function, ignore it, so that we don't get
3201: two entries (one from the .ent, and one for the .def
1.1.1.3 root 3202: that precedes it). Save the type information so that
1.1 root 3203: the end block can properly add it after the begin block
3204: index. For MIPS knows what reason, we must strip off
3205: the function type at this point. */
3206: if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
3207: {
3208: is_function = 1;
3209: tq_ptr[-1] = tq_Nil;
3210: }
3211:
3212: break;
3213: }
3214:
3215: else if (len == sizeof (".tag")-1
3216: && memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
3217: {
3218: tag_start = arg_start;
3219: tag_end_p1 = arg_end_p1;
3220: break;
3221: }
3222:
3223: else
3224: {
3225: error_line = __LINE__;
3226: saber_stop ();
3227: goto bomb_out;
3228: }
3229:
3230:
3231: case 'v':
3232: if (len == sizeof (".val")-1
3233: && memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
3234: {
3235: if (arg_was_number)
3236: value = arg_number;
3237:
3238: /* If the value is not an integer value, it must be the
3239: name of a static or global item. Look up the name in
1.1.1.3 root 3240: the original symbol table to pick up the storage
1.1 root 3241: class, symbol type, etc. */
3242: else
3243: {
3244: shash_t *orig_hash_ptr; /* hash within orig sym table*/
3245: shash_t *ext_hash_ptr; /* hash within ext. sym table*/
3246:
3247: ext_hash_ptr = hash_string (arg_start,
3248: arg_end_p1 - arg_start,
3249: &ext_str_hash[0],
3250: (symint_t *)0);
3251:
3252: if (ext_hash_ptr != (shash_t *)0
3253: && ext_hash_ptr->esym_ptr != (EXTR *)0)
3254: eptr = ext_hash_ptr->esym_ptr;
3255:
3256: orig_hash_ptr = hash_string (arg_start,
3257: arg_end_p1 - arg_start,
3258: &orig_str_hash[0],
3259: (symint_t *)0);
3260:
3261: if ((orig_hash_ptr == (shash_t *)0
3262: || orig_hash_ptr->sym_ptr == (SYMR *)0)
3263: && eptr == (EXTR *)0)
3264: {
3265: fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
3266: arg_end_p1 - arg_start,
3267: arg_start);
3268: value = 0;
3269: }
3270: else
3271: {
3272: SYMR *ptr = (orig_hash_ptr != (shash_t *)0
3273: && orig_hash_ptr->sym_ptr != (SYMR *)0)
3274: ? orig_hash_ptr->sym_ptr
3275: : &eptr->asym;
3276:
3277: symbol_type = (st_t) ptr->st;
3278: storage_class = (sc_t) ptr->sc;
3279: value = ptr->value;
3280: }
3281: }
3282: break;
3283: }
3284: else
3285: {
3286: error_line = __LINE__;
3287: saber_stop ();
3288: goto bomb_out;
3289: }
3290: }
3291:
3292: /* Set up to find next directive. */
3293: dir_start = arg_end_p1 + 1;
3294: }
3295:
3296:
3297: t.extra_sizes = (tag_start != (char *)0);
3298: if (t.num_dims > 0)
3299: {
3300: int diff = t.num_dims - t.num_sizes;
3301: int i = t.num_dims - 1;
3302: int j;
3303:
3304: if (t.num_sizes != 1 || diff < 0)
3305: {
3306: error_line = __LINE__;
3307: saber_stop ();
3308: goto bomb_out;
3309: }
3310:
3311: /* If this is an array, make sure the same number of dimensions
3312: and sizes were passed, creating extra sizes for multiply
3313: dimensioned arrays if not passed. */
3314:
3315: t.extra_sizes = 0;
3316: if (diff)
3317: {
3318: for (j = (sizeof (t.sizes) / sizeof (t.sizes[0])) - 1; j >= 0; j--)
3319: t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
3320:
3321: t.num_sizes = i + 1;
3322: for ( i--; i >= 0; i-- )
1.1.1.5 root 3323: {
3324: if (t.dimensions[ i+1 ])
3325: t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
3326: else
3327: t.sizes[ i ] = t.sizes[ i+1 ];
3328: }
1.1 root 3329: }
3330: }
3331:
3332: else if (symbol_type == st_Member && t.num_sizes - t.extra_sizes == 1)
1.1.1.8 ! root 3333: { /* Is this a bitfield? This is indicated by a structure member
1.1 root 3334: having a size field that isn't an array. */
3335:
3336: t.bitfield = 1;
3337: }
3338:
3339:
3340: /* Except for enumeration members & begin/ending of scopes, put the
3341: type word in the aux. symbol table. */
3342:
3343: if (symbol_type == st_Block || symbol_type == st_End)
1.1.1.4 root 3344: indx = 0;
1.1 root 3345:
3346: else if (inside_enumeration)
1.1.1.4 root 3347: indx = cur_file_ptr->void_type;
1.1 root 3348:
3349: else
3350: {
3351: if (t.basic_type == bt_Struct
3352: || t.basic_type == bt_Union
3353: || t.basic_type == bt_Enum)
3354: {
3355: if (tag_start == (char *)0)
3356: {
3357: error ("No tag specified for %.*s",
3358: name_end_p1 - name_start,
3359: name_start);
3360: return;
3361: }
3362:
3363: t.tag_ptr = get_tag (tag_start, tag_end_p1, (symint_t)indexNil,
3364: t.basic_type);
3365: }
3366:
3367: if (is_function)
3368: {
3369: last_func_type_info = t;
3370: last_func_eptr = eptr;
3371: return;
3372: }
3373:
1.1.1.4 root 3374: indx = add_aux_sym_tir (&t,
3375: hash_yes,
3376: &cur_file_ptr->thash_head[0]);
1.1 root 3377: }
3378:
3379:
3380: /* If this is an external or static symbol, update the appropriate
3381: external symbol. */
3382:
3383: if (eptr != (EXTR *)0
3384: && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *)0))
3385: {
3386: eptr->ifd = cur_file_ptr->file_index;
1.1.1.4 root 3387: eptr->asym.index = indx;
1.1 root 3388: }
3389:
3390:
3391: /* Do any last minute adjustments that are necessary. */
3392: switch (symbol_type)
3393: {
3394: default:
3395: break;
3396:
3397:
3398: /* For the beginning of structs, unions, and enumerations, the
3399: size info needs to be passed in the value field. */
3400:
3401: case st_Block:
3402: if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
3403: {
3404: error_line = __LINE__;
3405: saber_stop ();
3406: goto bomb_out;
3407: }
3408:
3409: else
3410: value = t.sizes[0];
3411:
3412: inside_enumeration = (t.orig_type == T_ENUM);
3413: break;
3414:
3415:
3416: /* For the end of structs, unions, and enumerations, omit the
3417: name which is always ".eos". This needs to be done last, so
3418: that any error reporting above gives the correct name. */
3419:
3420: case st_End:
3421: name_start = name_end_p1 = (const char *)0;
3422: value = inside_enumeration = 0;
3423: break;
3424:
3425:
3426: /* Members of structures and unions that aren't bitfields, need
3427: to adjust the value from a byte offset to a bit offset.
3428: Members of enumerations do not have the value adjusted, and
1.1.1.4 root 3429: can be distinguished by indx == indexNil. For enumerations,
1.1 root 3430: update the maximum enumeration value. */
3431:
3432: case st_Member:
3433: if (!t.bitfield && !inside_enumeration)
3434: value *= 8;
3435:
3436: break;
3437: }
3438:
3439:
3440: /* Add the symbol, except for global symbols outside of functions,
3441: for which the external symbol table is fine enough. */
3442:
3443: if (eptr == (EXTR *)0
3444: || eptr->asym.st == (int)st_Nil
3445: || cur_proc_ptr != (PDR *)0)
3446: {
3447: symint_t isym = add_local_symbol (name_start, name_end_p1,
3448: symbol_type, storage_class,
3449: value,
1.1.1.4 root 3450: indx);
1.1 root 3451:
3452: /* deal with struct, union, and enum tags. */
3453: if (symbol_type == st_Block)
3454: {
3455: /* Create or update the tag information. */
3456: tag_t *tag_ptr = get_tag (name_start,
3457: name_end_p1,
3458: isym,
3459: t.basic_type);
3460:
3461: /* If there are any forward references, fill in the appropriate
3462: file and symbol indexes. */
3463:
3464: symint_t file_index = cur_file_ptr->file_index;
3465: forward_t *f_next = tag_ptr->forward_ref;
3466: forward_t *f_cur;
3467:
3468: while (f_next != (forward_t *)0)
3469: {
3470: f_cur = f_next;
3471: f_next = f_next->next;
3472:
3473: f_cur->ifd_ptr->isym = file_index;
3474: f_cur->index_ptr->rndx.index = isym;
3475:
3476: free_forward (f_cur);
3477: }
3478:
3479: tag_ptr->forward_ref = (forward_t *)0;
3480: }
3481: }
3482:
3483: /* Normal return */
3484: return;
3485:
3486: /* Error return, issue message. */
3487: bomb_out:
3488: if (error_line)
3489: error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
3490: else
3491: error ("compiler error, badly formed #.def");
3492:
3493: return;
3494: }
3495:
3496:
3497: /* Parse .end directives. */
3498:
3499: STATIC void
3500: parse_end (start)
3501: const char *start; /* start of directive */
3502: {
3503: register const char *start_func, *end_func_p1;
3504: register int ch;
3505: register symint_t value;
3506: register FDR *orig_fdr;
3507:
3508: if (cur_file_ptr == (efdr_t *)0)
3509: {
1.1.1.2 root 3510: error (".end directive without a preceding .file directive");
1.1 root 3511: return;
3512: }
3513:
3514: if (cur_proc_ptr == (PDR *)0)
3515: {
1.1.1.2 root 3516: error (".end directive without a preceding .ent directive");
1.1 root 3517: return;
3518: }
3519:
3520: /* Get the function name, skipping whitespace. */
3521: for (start_func = start; isspace (*start_func); start_func++)
3522: ;
3523:
3524: ch = *start_func;
3525: if (!IS_ASM_IDENT (ch))
3526: {
3527: error (".end directive has no name");
3528: return;
3529: }
3530:
3531: for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3532: ;
3533:
3534:
3535: /* Get the value field for creating the end from the original object
3536: file (which we find by locating the procedure start, and using the
3537: pointer to the end+1 block and backing up. The index points to a
3538: two word aux. symbol, whose first word is the index of the end
3539: symbol, and the second word is the type of the function return
3540: value. */
3541:
3542: orig_fdr = cur_file_ptr->orig_fdr;
3543: value = 0;
3544: if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *)0)
3545: value = cur_oproc_end->value;
3546:
3547: else
3548: error ("Cannot find .end block for %.*s", end_func_p1 - start_func, start_func);
3549:
3550: (void) add_local_symbol (start_func, end_func_p1,
3551: st_End, sc_Text,
3552: value,
3553: (symint_t)0);
3554:
3555: cur_proc_ptr = cur_oproc_ptr = (PDR *)0;
3556: }
3557:
3558:
3559: /* Parse .ent directives. */
3560:
3561: STATIC void
3562: parse_ent (start)
3563: const char *start; /* start of directive */
3564: {
3565: register const char *start_func, *end_func_p1;
3566: register int ch;
3567:
3568: if (cur_file_ptr == (efdr_t *)0)
3569: {
1.1.1.2 root 3570: error (".ent directive without a preceding .file directive");
1.1 root 3571: return;
3572: }
3573:
3574: if (cur_proc_ptr != (PDR *)0)
3575: {
3576: error ("second .ent directive found before .end directive");
3577: return;
3578: }
3579:
3580: for (start_func = start; isspace (*start_func); start_func++)
3581: ;
3582:
3583: ch = *start_func;
3584: if (!IS_ASM_IDENT (ch))
3585: {
3586: error (".ent directive has no name");
3587: return;
3588: }
3589:
3590: for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
3591: ;
3592:
3593: (void) add_procedure (start_func, end_func_p1);
3594: }
3595:
3596:
3597: /* Parse .file directives. */
3598:
3599: STATIC void
3600: parse_file (start)
3601: const char *start; /* start of directive */
3602: {
3603: char *p;
3604: register char *start_name, *end_name_p1;
3605:
3606: (void) strtol (start, &p, 0);
3607: if (start == p
1.1.1.4 root 3608: || (start_name = local_index (p, '"')) == (char *)0
3609: || (end_name_p1 = local_rindex (++start_name, '"')) == (char *)0)
1.1 root 3610: {
1.1.1.5 root 3611: error ("Invalid .file directive");
1.1 root 3612: return;
3613: }
3614:
3615: if (cur_proc_ptr != (PDR *)0)
3616: {
3617: error ("No way to handle .file within .ent/.end section");
3618: return;
3619: }
3620:
3621: add_file (start_name, end_name_p1);
3622: }
3623:
3624:
1.1.1.2 root 3625: /* Make sure the @stabs symbol is emitted. */
3626:
3627: static void
3628: mark_stabs (start)
3629: const char *start; /* Start of directive (ignored) */
3630: {
3631: if (!stabs_seen)
3632: {
1.1.1.8 ! root 3633: /* Add a dummy @stabs symbol. */
1.1.1.2 root 3634: stabs_seen = 1;
3635: (void) add_local_symbol (stabs_symbol,
3636: stabs_symbol + sizeof (stabs_symbol),
3637: stNil, scInfo, -1, MIPS_MARK_STAB(0));
3638:
3639: }
3640: }
3641:
3642:
1.1 root 3643: /* Parse .stabs directives.
3644:
3645: .stabs directives have five fields:
3646: "string" a string, encoding the type information.
3647: code a numeric code, defined in <stab.h>
3648: 0 a zero
3649: 0 a zero or line number
3650: value a numeric value or an address.
3651:
3652: If the value is relocatable, we transform this into:
3653: iss points as an index into string space
3654: value value from lookup of the name
3655: st st from lookup of the name
3656: sc sc from lookup of the name
3657: index code|CODE_MASK
3658:
3659: If the value is not relocatable, we transform this into:
3660: iss points as an index into string space
3661: value value
3662: st st_Nil
3663: sc sc_Nil
3664: index code|CODE_MASK
3665:
3666: .stabn directives have four fields (string is null):
3667: code a numeric code, defined in <stab.h>
3668: 0 a zero
3669: 0 a zero or a line number
3670: value a numeric value or an address. */
3671:
3672: STATIC void
3673: parse_stabs_common (string_start, string_end, rest)
3674: const char *string_start; /* start of string or NULL */
3675: const char *string_end; /* end+1 of string or NULL */
3676: const char *rest; /* rest of the directive. */
3677: {
3678: efdr_t *save_file_ptr = cur_file_ptr;
3679: symint_t code;
3680: symint_t value;
3681: char *p;
3682: st_t st;
3683: sc_t sc;
3684: int ch;
3685:
1.1.1.2 root 3686: if (stabs_seen == 0)
3687: mark_stabs ("");
1.1 root 3688:
3689: /* Read code from stabs. */
3690: if (!isdigit (*rest))
3691: {
1.1.1.5 root 3692: error ("Invalid .stabs/.stabn directive, code is non-numeric");
1.1 root 3693: return;
3694: }
3695:
3696: code = strtol (rest, &p, 0);
3697:
3698: /* Line number stabs are handled differently, since they have two values,
3699: the line number and the address of the label. We use the index field
3700: (aka code) to hold the line number, and the value field to hold the
3701: address. The symbol type is st_Label, which should be different from
3702: the other stabs, so that gdb can recognize it. */
3703:
3704: if (code == (int)N_SLINE)
3705: {
1.1.1.4 root 3706: SYMR *sym_ptr, dummy_symr;
1.1 root 3707: shash_t *shash_ptr;
3708:
3709: /* Skip ,0, */
3710: if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !isdigit (p[3]))
3711: {
1.1.1.5 root 3712: error ("Invalid line number .stabs/.stabn directive");
1.1 root 3713: return;
3714: }
3715:
3716: code = strtol (p+3, &p, 0);
3717: ch = *++p;
1.1.1.4 root 3718: if (p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch))
1.1 root 3719: {
1.1.1.5 root 3720: error ("Invalid line number .stabs/.stabn directive");
1.1 root 3721: return;
3722: }
3723:
1.1.1.4 root 3724: dummy_symr.index = code;
3725: if (dummy_symr.index != code)
3726: {
3727: error ("Line number (%d) for .stabs/.stabn directive cannot fit in index field (20 bits)",
3728: code);
3729:
3730: return;
3731: }
3732:
1.1 root 3733: shash_ptr = hash_string (p,
3734: strlen (p) - 1,
3735: &orig_str_hash[0],
3736: (symint_t *)0);
3737:
3738: if (shash_ptr == (shash_t *)0
3739: || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
3740: {
1.1.1.5 root 3741: error ("Invalid .stabs/.stabn directive, value not found");
1.1 root 3742: return;
3743: }
3744:
3745: if ((st_t) sym_ptr->st != st_Label)
3746: {
1.1.1.5 root 3747: error ("Invalid line number .stabs/.stabn directive");
1.1 root 3748: return;
3749: }
3750:
3751: st = st_Label;
3752: sc = (sc_t) sym_ptr->sc;
3753: value = sym_ptr->value;
3754: }
3755: else
3756: {
1.1.1.5 root 3757: /* Skip ,<num>,<num>, */
3758: if (*p++ != ',')
3759: goto failure;
3760: for (; isdigit (*p); p++)
3761: ;
3762: if (*p++ != ',')
3763: goto failure;
3764: for (; isdigit (*p); p++)
3765: ;
3766: if (*p++ != ',')
3767: goto failure;
1.1 root 3768: ch = *p;
3769: if (!IS_ASM_IDENT (ch) && ch != '-')
3770: {
1.1.1.5 root 3771: failure:
3772: error ("Invalid .stabs/.stabn directive, bad character");
1.1 root 3773: return;
3774: }
3775:
3776: if (isdigit (ch) || ch == '-')
3777: {
3778: st = st_Nil;
3779: sc = sc_Nil;
3780: value = strtol (p, &p, 0);
3781: if (*p != '\n')
3782: {
1.1.1.5 root 3783: error ("Invalid .stabs/.stabn directive, stuff after numeric value");
1.1 root 3784: return;
3785: }
3786: }
3787: else if (!IS_ASM_IDENT (ch))
3788: {
1.1.1.5 root 3789: error ("Invalid .stabs/.stabn directive, bad character");
1.1 root 3790: return;
3791: }
3792: else
3793: {
3794: SYMR *sym_ptr;
1.1.1.4 root 3795: shash_t *shash_ptr;
3796: const char *start, *end_p1;
3797:
3798: start = p;
3799: if ((end_p1 = strchr (start, '+')) == (char *)0)
3800: {
3801: if ((end_p1 = strchr (start, '-')) == (char *)0)
3802: end_p1 = start + strlen(start) - 1;
3803: }
3804:
3805: shash_ptr = hash_string (start,
3806: end_p1 - start,
3807: &orig_str_hash[0],
3808: (symint_t *)0);
1.1 root 3809:
3810: if (shash_ptr == (shash_t *)0
3811: || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
3812: {
1.1.1.4 root 3813: shash_ptr = hash_string (start,
3814: end_p1 - start,
3815: &ext_str_hash[0],
3816: (symint_t *)0);
3817:
3818: if (shash_ptr == (shash_t *)0
3819: || shash_ptr->esym_ptr == (EXTR *)0)
3820: {
1.1.1.5 root 3821: error ("Invalid .stabs/.stabn directive, value not found");
1.1.1.4 root 3822: return;
3823: }
3824: else
3825: sym_ptr = &(shash_ptr->esym_ptr->asym);
1.1 root 3826: }
3827:
3828: /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
3829: if (code == (int)N_LBRAC || code == (int)N_RBRAC)
3830: {
3831: sc = scNil;
3832: st = stNil;
3833: }
3834: else
3835: {
3836: sc = (sc_t) sym_ptr->sc;
3837: st = (st_t) sym_ptr->st;
3838: }
3839: value = sym_ptr->value;
1.1.1.4 root 3840:
3841: ch = *end_p1++;
3842: if (ch != '\n')
3843: {
3844: if (((!isdigit (*end_p1)) && (*end_p1 != '-'))
3845: || ((ch != '+') && (ch != '-')))
3846: {
1.1.1.5 root 3847: error ("Invalid .stabs/.stabn directive, badly formed value");
1.1.1.4 root 3848: return;
3849: }
3850: if (ch == '+')
3851: value += strtol (end_p1, &p, 0);
3852: else if (ch == '-')
3853: value -= strtol (end_p1, &p, 0);
3854:
3855: if (*p != '\n')
3856: {
1.1.1.5 root 3857: error ("Invalid .stabs/.stabn directive, stuff after numeric value");
1.1.1.4 root 3858: return;
3859: }
3860: }
1.1 root 3861: }
3862: code = MIPS_MARK_STAB(code);
3863: }
3864:
3865: (void) add_local_symbol (string_start, string_end, st, sc, value, code);
3866: /* Restore normal file type. */
3867: cur_file_ptr = save_file_ptr;
3868: }
3869:
3870:
3871: STATIC void
3872: parse_stabs (start)
3873: const char *start; /* start of directive */
3874: {
1.1.1.4 root 3875: const char *end = local_index (start+1, '"');
1.1 root 3876:
3877: if (*start != '"' || end == (const char *)0 || end[1] != ',')
3878: {
1.1.1.5 root 3879: error ("Invalid .stabs directive, no string");
1.1 root 3880: return;
3881: }
3882:
3883: parse_stabs_common (start+1, end, end+2);
3884: }
3885:
3886:
3887: STATIC void
3888: parse_stabn (start)
3889: const char *start; /* start of directive */
3890: {
3891: parse_stabs_common ((const char *)0, (const char *)0, start);
3892: }
3893:
3894:
3895: /* Parse the input file, and write the lines to the output file
3896: if needed. */
3897:
3898: STATIC void
3899: parse_input __proto((void))
3900: {
3901: register char *p;
3902: register int i;
3903: register thead_t *ptag_head;
3904: register tag_t *ptag;
3905: register tag_t *ptag_next;
3906:
3907: if (debug)
3908: fprintf (stderr, "\tinput\n");
3909:
3910: /* Add a dummy scope block around the entire compilation unit for
3911: structures defined outside of blocks. */
3912: ptag_head = allocate_thead ();
3913: ptag_head->first_tag = 0;
3914: ptag_head->prev = cur_tag_head;
3915: cur_tag_head = ptag_head;
3916:
3917: while ((p = read_line ()) != (char *)0)
3918: {
3919: /* Skip leading blanks */
3920: while (isspace (*p))
3921: p++;
3922:
3923: /* See if it's a directive we handle. If so, dispatch handler. */
3924: for (i = 0; i < sizeof (pseudo_ops) / sizeof (pseudo_ops[0]); i++)
3925: if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
3926: && isspace (p[pseudo_ops[i].len]))
3927: {
3928: p += pseudo_ops[i].len; /* skip to first argument */
3929: while (isspace (*p))
3930: p++;
3931:
3932: (*pseudo_ops[i].func)( p );
3933: break;
3934: }
3935: }
3936:
3937: /* Process any tags at global level. */
3938: ptag_head = cur_tag_head;
3939: cur_tag_head = ptag_head->prev;
3940:
3941: for (ptag = ptag_head->first_tag;
3942: ptag != (tag_t *)0;
3943: ptag = ptag_next)
3944: {
3945: if (ptag->forward_ref != (forward_t *)0)
3946: add_unknown_tag (ptag);
3947:
3948: ptag_next = ptag->same_block;
3949: ptag->hash_ptr->tag_ptr = ptag->same_name;
3950: free_tag (ptag);
3951: }
3952:
3953: free_thead (ptag_head);
3954:
3955: }
3956:
3957:
3958: /* Update the global headers with the final offsets in preparation
3959: to write out the .T file. */
3960:
3961: STATIC void
3962: update_headers __proto((void))
3963: {
3964: register symint_t i;
3965: register efdr_t *file_ptr;
3966:
3967: /* Set up the symbolic header. */
3968: file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
3969: symbolic_header.magic = orig_sym_hdr.magic;
3970: symbolic_header.vstamp = orig_sym_hdr.vstamp;
3971:
3972: /* Set up global counts. */
3973: symbolic_header.issExtMax = ext_strings.num_allocated;
3974: symbolic_header.idnMax = dense_num.num_allocated;
3975: symbolic_header.ifdMax = file_desc.num_allocated;
3976: symbolic_header.iextMax = ext_symbols.num_allocated;
3977: symbolic_header.ilineMax = orig_sym_hdr.ilineMax;
3978: symbolic_header.ioptMax = orig_sym_hdr.ioptMax;
3979: symbolic_header.cbLine = orig_sym_hdr.cbLine;
3980: symbolic_header.crfd = orig_sym_hdr.crfd;
3981:
3982:
3983: /* Loop through each file, figuring out how many local syms,
3984: line numbers, etc. there are. Also, put out end symbol
3985: for the filename. */
3986:
3987: for (file_ptr = first_file;
3988: file_ptr != (efdr_t *)0;
3989: file_ptr = file_ptr->next_file)
3990: {
1.1.1.7 root 3991: register SYMR *sym_start;
3992: register SYMR *sym;
3993: register SYMR *sym_end_p1;
3994: register FDR *fd_ptr = file_ptr->orig_fdr;
3995:
1.1 root 3996: cur_file_ptr = file_ptr;
1.1.1.7 root 3997:
3998: /* Copy st_Static symbols from the original local symbol table if
3999: they did not get added to the new local symbol table.
4000: This happens with stabs-in-ecoff or if the source file is
4001: compiled without debugging. */
4002: sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4003: sym_end_p1 = sym_start + fd_ptr->csym;
4004: for (sym = sym_start; sym < sym_end_p1; sym++)
4005: {
4006: if ((st_t)sym->st == st_Static)
4007: {
4008: register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4009: register Size_t len = strlen (str);
4010: register shash_t *hash_ptr;
4011:
4012: /* Ignore internal labels. */
4013: if (str[0] == '$' && str[1] == 'L')
4014: continue;
4015: hash_ptr = hash_string (str,
4016: (Ptrdiff_t)len,
4017: &file_ptr->shash_head[0],
4018: (symint_t *)0);
4019: if (hash_ptr == (shash_t *)0)
4020: {
4021: (void) add_local_symbol (str, str + len,
4022: (st_t)sym->st, (sc_t)sym->sc,
4023: (symint_t)sym->value,
4024: (symint_t)indexNil);
4025: }
4026: }
4027: }
1.1 root 4028: (void) add_local_symbol ((const char *)0, (const char *)0,
4029: st_End, sc_Text,
4030: (symint_t)0,
4031: (symint_t)0);
4032:
4033: file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
4034: file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
4035: symbolic_header.ipdMax += file_ptr->fdr.cpd;
4036:
4037: file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
4038: file_ptr->fdr.isymBase = symbolic_header.isymMax;
4039: symbolic_header.isymMax += file_ptr->fdr.csym;
4040:
4041: file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
4042: file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
4043: symbolic_header.iauxMax += file_ptr->fdr.caux;
4044:
4045: file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
4046: file_ptr->fdr.issBase = symbolic_header.issMax;
4047: symbolic_header.issMax += file_ptr->fdr.cbSs;
4048: }
4049:
1.1.1.7 root 4050: #ifndef ALIGN_SYMTABLE_OFFSET
4051: #define ALIGN_SYMTABLE_OFFSET(OFFSET) (OFFSET)
4052: #endif
1.1 root 4053:
1.1.1.7 root 4054: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4055: i = WORD_ALIGN (symbolic_header.cbLine); /* line numbers */
4056: if (i > 0)
4057: {
4058: symbolic_header.cbLineOffset = file_offset;
4059: file_offset += i;
1.1.1.7 root 4060: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4061: }
4062:
4063: i = symbolic_header.ioptMax; /* optimization symbols */
4064: if (((long) i) > 0)
4065: {
4066: symbolic_header.cbOptOffset = file_offset;
4067: file_offset += i * sizeof (OPTR);
1.1.1.7 root 4068: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4069: }
4070:
4071: i = symbolic_header.idnMax; /* dense numbers */
4072: if (i > 0)
4073: {
4074: symbolic_header.cbDnOffset = file_offset;
4075: file_offset += i * sizeof (DNR);
1.1.1.7 root 4076: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4077: }
4078:
4079: i = symbolic_header.ipdMax; /* procedure tables */
4080: if (i > 0)
4081: {
4082: symbolic_header.cbPdOffset = file_offset;
4083: file_offset += i * sizeof (PDR);
1.1.1.7 root 4084: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4085: }
4086:
4087: i = symbolic_header.isymMax; /* local symbols */
4088: if (i > 0)
4089: {
4090: symbolic_header.cbSymOffset = file_offset;
4091: file_offset += i * sizeof (SYMR);
1.1.1.7 root 4092: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4093: }
4094:
4095: i = symbolic_header.iauxMax; /* aux syms. */
4096: if (i > 0)
4097: {
4098: symbolic_header.cbAuxOffset = file_offset;
4099: file_offset += i * sizeof (TIR);
1.1.1.7 root 4100: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4101: }
4102:
4103: i = WORD_ALIGN (symbolic_header.issMax); /* local strings */
4104: if (i > 0)
4105: {
4106: symbolic_header.cbSsOffset = file_offset;
4107: file_offset += i;
1.1.1.7 root 4108: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4109: }
4110:
4111: i = WORD_ALIGN (symbolic_header.issExtMax); /* external strings */
4112: if (i > 0)
4113: {
4114: symbolic_header.cbSsExtOffset = file_offset;
4115: file_offset += i;
1.1.1.7 root 4116: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4117: }
4118:
4119: i = symbolic_header.ifdMax; /* file tables */
4120: if (i > 0)
4121: {
4122: symbolic_header.cbFdOffset = file_offset;
4123: file_offset += i * sizeof (FDR);
1.1.1.7 root 4124: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4125: }
4126:
4127: i = symbolic_header.crfd; /* relative file descriptors */
4128: if (i > 0)
4129: {
4130: symbolic_header.cbRfdOffset = file_offset;
4131: file_offset += i * sizeof (symint_t);
1.1.1.7 root 4132: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4133: }
4134:
4135: i = symbolic_header.iextMax; /* external symbols */
4136: if (i > 0)
4137: {
4138: symbolic_header.cbExtOffset = file_offset;
4139: file_offset += i * sizeof (EXTR);
1.1.1.7 root 4140: file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
1.1 root 4141: }
4142: }
4143:
4144:
4145: /* Write out a varray at a given location. */
4146:
4147: STATIC void
4148: write_varray (vp, offset, str)
4149: varray_t *vp; /* virtual array */
4150: off_t offset; /* offset to write varray to */
4151: const char *str; /* string to print out when tracing */
4152: {
4153: int num_write, sys_write;
4154: vlinks_t *ptr;
4155:
4156: if (vp->num_allocated == 0)
4157: return;
4158:
4159: if (debug)
4160: fprintf (stderr, "\twarray\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4161: vp, offset, vp->num_allocated * vp->object_size, str);
4162:
4163: if (file_offset != offset
4164: && fseek (object_stream, (long)offset, SEEK_SET) < 0)
4165: pfatal_with_name (object_name);
4166:
4167: for (ptr = vp->first; ptr != (vlinks_t *)0; ptr = ptr->next)
4168: {
4169: num_write = (ptr->next == (vlinks_t *)0)
4170: ? vp->objects_last_page * vp->object_size
4171: : vp->objects_per_page * vp->object_size;
4172:
4173: sys_write = fwrite ((PTR_T) ptr->datum, 1, num_write, object_stream);
4174: if (sys_write <= 0)
4175: pfatal_with_name (object_name);
4176:
4177: else if (sys_write != num_write)
4178: fatal ("Wrote %d bytes to %s, system returned %d",
4179: num_write,
4180: object_name,
4181: sys_write);
4182:
4183: file_offset += num_write;
4184: }
4185: }
4186:
4187:
4188: /* Write out the symbol table in the object file. */
4189:
4190: STATIC void
4191: write_object __proto((void))
4192: {
4193: int sys_write;
4194: efdr_t *file_ptr;
4195: off_t offset;
4196:
4197: if (debug)
4198: fprintf (stderr, "\n\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4199: (PTR_T *) &symbolic_header, 0, sizeof (symbolic_header),
4200: "symbolic header");
4201:
4202: sys_write = fwrite ((PTR_T) &symbolic_header,
4203: 1,
4204: sizeof (symbolic_header),
4205: object_stream);
4206:
4207: if (sys_write < 0)
4208: pfatal_with_name (object_name);
4209:
4210: else if (sys_write != sizeof (symbolic_header))
4211: fatal ("Wrote %d bytes to %s, system returned %d",
4212: sizeof (symbolic_header),
4213: object_name,
4214: sys_write);
4215:
4216:
4217: file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
4218:
4219: if (symbolic_header.cbLine > 0) /* line numbers */
4220: {
4221: long sys_write;
4222:
4223: if (file_offset != symbolic_header.cbLineOffset
4224: && fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
4225: pfatal_with_name (object_name);
4226:
4227: if (debug)
4228: fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4229: (PTR_T *) &orig_linenum, symbolic_header.cbLineOffset,
4230: symbolic_header.cbLine, "Line numbers");
4231:
4232: sys_write = fwrite ((PTR_T) orig_linenum,
4233: 1,
4234: symbolic_header.cbLine,
4235: object_stream);
4236:
4237: if (sys_write <= 0)
4238: pfatal_with_name (object_name);
4239:
4240: else if (sys_write != symbolic_header.cbLine)
4241: fatal ("Wrote %d bytes to %s, system returned %d",
4242: symbolic_header.cbLine,
4243: object_name,
4244: sys_write);
4245:
4246: file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
4247: }
4248:
4249: if (symbolic_header.ioptMax > 0) /* optimization symbols */
4250: {
4251: long sys_write;
4252: long num_write = symbolic_header.ioptMax * sizeof (OPTR);
4253:
4254: if (file_offset != symbolic_header.cbOptOffset
4255: && fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
4256: pfatal_with_name (object_name);
4257:
4258: if (debug)
4259: fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4260: (PTR_T *) &orig_opt_syms, symbolic_header.cbOptOffset,
4261: num_write, "Optimizer symbols");
4262:
4263: sys_write = fwrite ((PTR_T) orig_opt_syms,
4264: 1,
4265: num_write,
4266: object_stream);
4267:
4268: if (sys_write <= 0)
4269: pfatal_with_name (object_name);
4270:
4271: else if (sys_write != num_write)
4272: fatal ("Wrote %d bytes to %s, system returned %d",
4273: num_write,
4274: object_name,
4275: sys_write);
4276:
4277: file_offset = symbolic_header.cbOptOffset + num_write;
4278: }
4279:
4280: if (symbolic_header.idnMax > 0) /* dense numbers */
4281: write_varray (&dense_num, (off_t)symbolic_header.cbDnOffset, "Dense numbers");
4282:
4283: if (symbolic_header.ipdMax > 0) /* procedure tables */
4284: {
4285: offset = symbolic_header.cbPdOffset;
4286: for (file_ptr = first_file;
4287: file_ptr != (efdr_t *)0;
4288: file_ptr = file_ptr->next_file)
4289: {
4290: write_varray (&file_ptr->procs, offset, "Procedure tables");
4291: offset = file_offset;
4292: }
4293: }
4294:
4295: if (symbolic_header.isymMax > 0) /* local symbols */
4296: {
4297: offset = symbolic_header.cbSymOffset;
4298: for (file_ptr = first_file;
4299: file_ptr != (efdr_t *)0;
4300: file_ptr = file_ptr->next_file)
4301: {
4302: write_varray (&file_ptr->symbols, offset, "Local symbols");
4303: offset = file_offset;
4304: }
4305: }
4306:
4307: if (symbolic_header.iauxMax > 0) /* aux symbols */
4308: {
4309: offset = symbolic_header.cbAuxOffset;
4310: for (file_ptr = first_file;
4311: file_ptr != (efdr_t *)0;
4312: file_ptr = file_ptr->next_file)
4313: {
4314: write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
4315: offset = file_offset;
4316: }
4317: }
4318:
4319: if (symbolic_header.issMax > 0) /* local strings */
4320: {
4321: offset = symbolic_header.cbSsOffset;
4322: for (file_ptr = first_file;
4323: file_ptr != (efdr_t *)0;
4324: file_ptr = file_ptr->next_file)
4325: {
4326: write_varray (&file_ptr->strings, offset, "Local strings");
4327: offset = file_offset;
4328: }
4329: }
4330:
4331: if (symbolic_header.issExtMax > 0) /* external strings */
4332: write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
4333:
4334: if (symbolic_header.ifdMax > 0) /* file tables */
4335: {
4336: offset = symbolic_header.cbFdOffset;
4337: if (file_offset != offset
4338: && fseek (object_stream, (long)offset, SEEK_SET) < 0)
4339: pfatal_with_name (object_name);
4340:
4341: file_offset = offset;
4342: for (file_ptr = first_file;
4343: file_ptr != (efdr_t *)0;
4344: file_ptr = file_ptr->next_file)
4345: {
4346: if (debug)
4347: fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4348: (PTR_T *) &file_ptr->fdr, file_offset, sizeof (FDR), "File header");
4349:
4350: sys_write = fwrite (&file_ptr->fdr,
4351: 1,
4352: sizeof (FDR),
4353: object_stream);
4354:
4355: if (sys_write < 0)
4356: pfatal_with_name (object_name);
4357:
4358: else if (sys_write != sizeof (FDR))
4359: fatal ("Wrote %d bytes to %s, system returned %d",
4360: sizeof (FDR),
4361: object_name,
4362: sys_write);
4363:
4364: file_offset = offset += sizeof (FDR);
4365: }
4366: }
4367:
4368: if (symbolic_header.crfd > 0) /* relative file descriptors */
4369: {
4370: long sys_write;
4371: symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
4372:
4373: if (file_offset != symbolic_header.cbRfdOffset
4374: && fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
4375: pfatal_with_name (object_name);
4376:
4377: if (debug)
4378: fprintf (stderr, "\twrite\tvp = 0x%.8x, offset = %7u, size = %7u, %s\n",
4379: (PTR_T *) &orig_rfds, symbolic_header.cbRfdOffset,
4380: num_write, "Relative file descriptors");
4381:
4382: sys_write = fwrite (orig_rfds,
4383: 1,
4384: num_write,
4385: object_stream);
4386:
4387: if (sys_write <= 0)
4388: pfatal_with_name (object_name);
4389:
4390: else if (sys_write != num_write)
4391: fatal ("Wrote %d bytes to %s, system returned %d",
4392: num_write,
4393: object_name,
4394: sys_write);
4395:
4396: file_offset = symbolic_header.cbRfdOffset + num_write;
4397: }
4398:
4399: if (symbolic_header.issExtMax > 0) /* external symbols */
4400: write_varray (&ext_symbols, (off_t)symbolic_header.cbExtOffset, "External symbols");
4401:
4402: if (fclose (object_stream) != 0)
4403: pfatal_with_name (object_name);
4404: }
4405:
4406:
4407: /* Read some bytes at a specified location, and return a pointer. */
4408:
4409: STATIC page_t *
4410: read_seek (size, offset, str)
4411: Size_t size; /* # bytes to read */
4412: off_t offset; /* offset to read at */
4413: const char *str; /* name for tracing */
4414: {
4415: page_t *ptr;
4416: long sys_read = 0;
4417:
4418: if (size == 0) /* nothing to read */
4419: return (page_t *)0;
4420:
4421: if (debug)
4422: fprintf (stderr, "\trseek\tsize = %7u, offset = %7u, currently at %7u, %s\n",
4423: size, offset, file_offset, str);
4424:
4425: #ifndef MALLOC_CHECK
4426: ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
4427: #else
4428: ptr = (page_t *) xcalloc (1, size);
4429: #endif
4430:
4431: /* If we need to seek, and the distance is nearby, just do some reads,
4432: to speed things up. */
4433: if (file_offset != offset)
4434: {
4435: symint_t difference = offset - file_offset;
4436:
4437: if (difference < 8)
4438: {
4439: char small_buffer[8];
4440:
4441: sys_read = fread (small_buffer, 1, difference, obj_in_stream);
4442: if (sys_read <= 0)
4443: pfatal_with_name (obj_in_name);
4444:
4445: if (sys_read != difference)
4446: fatal ("Wanted to read %d bytes from %s, system returned %d",
4447: size,
1.1.1.3 root 4448: obj_in_name,
4449: sys_read);
1.1 root 4450: }
4451: else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
4452: pfatal_with_name (obj_in_name);
4453: }
4454:
4455: sys_read = fread ((PTR_T)ptr, 1, size, obj_in_stream);
4456: if (sys_read <= 0)
4457: pfatal_with_name (obj_in_name);
4458:
4459: if (sys_read != size)
4460: fatal ("Wanted to read %d bytes from %s, system returned %d",
4461: size,
1.1.1.3 root 4462: obj_in_name,
4463: sys_read);
1.1 root 4464:
4465: file_offset = offset + size;
4466:
4467: if (file_offset > max_file_offset)
4468: max_file_offset = file_offset;
4469:
4470: return ptr;
4471: }
4472:
4473:
4474: /* Read the existing object file (and copy to the output object file
4475: if it is different from the input object file), and remove the old
4476: symbol table. */
4477:
4478: STATIC void
4479: copy_object __proto((void))
4480: {
4481: char buffer[ PAGE_SIZE ];
4482: register int sys_read;
4483: register int remaining;
4484: register int num_write;
4485: register int sys_write;
4486: register int fd, es;
4487: register int delete_ifd = 0;
4488: register int *remap_file_number;
4489: struct stat stat_buf;
4490:
4491: if (debug)
4492: fprintf (stderr, "\tcopy\n");
4493:
4494: if (fstat (fileno (obj_in_stream), &stat_buf) != 0
4495: || fseek (obj_in_stream, 0L, SEEK_SET) != 0)
4496: pfatal_with_name (obj_in_name);
4497:
4498: sys_read = fread ((PTR_T) &orig_file_header,
4499: 1,
4500: sizeof (struct filehdr),
4501: obj_in_stream);
4502:
4503: if (sys_read < 0)
4504: pfatal_with_name (obj_in_name);
4505:
4506: else if (sys_read == 0 && feof (obj_in_stream))
4507: return; /* create a .T file sans file header */
4508:
4509: else if (sys_read < sizeof (struct filehdr))
4510: fatal ("Wanted to read %d bytes from %s, system returned %d",
4511: sizeof (struct filehdr),
4512: obj_in_name,
4513: sys_read);
4514:
4515:
4516: if (orig_file_header.f_nsyms != sizeof (HDRR))
4517: fatal ("%s symbolic header wrong size (%d bytes, should be %d)",
4518: input_name, orig_file_header.f_nsyms, sizeof (HDRR));
4519:
4520:
4521: /* Read in the current symbolic header. */
4522: if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
4523: pfatal_with_name (input_name);
4524:
4525: sys_read = fread ((PTR_T) &orig_sym_hdr,
4526: 1,
4527: sizeof (orig_sym_hdr),
4528: obj_in_stream);
4529:
4530: if (sys_read < 0)
4531: pfatal_with_name (object_name);
4532:
4533: else if (sys_read < sizeof (struct filehdr))
4534: fatal ("Wanted to read %d bytes from %s, system returned %d",
4535: sizeof (struct filehdr),
4536: obj_in_name,
4537: sys_read);
4538:
4539:
4540: /* Read in each of the sections if they exist in the object file.
4541: We read things in in the order the mips assembler creates the
4542: sections, so in theory no extra seeks are done.
4543:
4544: For simplicity sake, round each read up to a page boundary,
4545: we may want to revisit this later.... */
4546:
4547: file_offset = orig_file_header.f_symptr + sizeof (struct filehdr);
4548:
4549: if (orig_sym_hdr.cbLine > 0) /* line numbers */
4550: orig_linenum = (char *) read_seek ((Size_t)orig_sym_hdr.cbLine,
4551: orig_sym_hdr.cbLineOffset,
4552: "Line numbers");
4553:
4554: if (orig_sym_hdr.ipdMax > 0) /* procedure tables */
4555: orig_procs = (PDR *) read_seek ((Size_t)orig_sym_hdr.ipdMax * sizeof (PDR),
4556: orig_sym_hdr.cbPdOffset,
4557: "Procedure tables");
4558:
4559: if (orig_sym_hdr.isymMax > 0) /* local symbols */
4560: orig_local_syms = (SYMR *) read_seek ((Size_t)orig_sym_hdr.isymMax * sizeof (SYMR),
4561: orig_sym_hdr.cbSymOffset,
4562: "Local symbols");
4563:
4564: if (orig_sym_hdr.iauxMax > 0) /* aux symbols */
4565: orig_aux_syms = (AUXU *) read_seek ((Size_t)orig_sym_hdr.iauxMax * sizeof (AUXU),
4566: orig_sym_hdr.cbAuxOffset,
4567: "Aux. symbols");
4568:
4569: if (orig_sym_hdr.issMax > 0) /* local strings */
4570: orig_local_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issMax,
4571: orig_sym_hdr.cbSsOffset,
4572: "Local strings");
4573:
4574: if (orig_sym_hdr.issExtMax > 0) /* external strings */
4575: orig_ext_strs = (char *) read_seek ((Size_t)orig_sym_hdr.issExtMax,
4576: orig_sym_hdr.cbSsExtOffset,
4577: "External strings");
4578:
4579: if (orig_sym_hdr.ifdMax > 0) /* file tables */
4580: orig_files = (FDR *) read_seek ((Size_t)orig_sym_hdr.ifdMax * sizeof (FDR),
4581: orig_sym_hdr.cbFdOffset,
4582: "File tables");
4583:
4584: if (orig_sym_hdr.crfd > 0) /* relative file descriptors */
4585: orig_rfds = (symint_t *) read_seek ((Size_t)orig_sym_hdr.crfd * sizeof (symint_t),
4586: orig_sym_hdr.cbRfdOffset,
4587: "Relative file descriptors");
4588:
4589: if (orig_sym_hdr.issExtMax > 0) /* external symbols */
4590: orig_ext_syms = (EXTR *) read_seek ((Size_t)orig_sym_hdr.iextMax * sizeof (EXTR),
4591: orig_sym_hdr.cbExtOffset,
4592: "External symbols");
4593:
4594: if (orig_sym_hdr.idnMax > 0) /* dense numbers */
4595: {
4596: orig_dense = (DNR *) read_seek ((Size_t)orig_sym_hdr.idnMax * sizeof (DNR),
4597: orig_sym_hdr.cbDnOffset,
4598: "Dense numbers");
4599:
4600: add_bytes (&dense_num, (char *) orig_dense, (Size_t)orig_sym_hdr.idnMax);
4601: }
4602:
4603: if (orig_sym_hdr.ioptMax > 0) /* opt symbols */
4604: orig_opt_syms = (OPTR *) read_seek ((Size_t)orig_sym_hdr.ioptMax * sizeof (OPTR),
4605: orig_sym_hdr.cbOptOffset,
4606: "Optimizer symbols");
4607:
4608:
4609:
4610: /* Abort if the symbol table is not last. */
4611: if (max_file_offset != stat_buf.st_size)
4612: fatal ("Symbol table is not last (symbol table ends at %ld, .o ends at %ld",
4613: max_file_offset,
4614: stat_buf.st_size);
4615:
4616:
4617: /* If the first original file descriptor is a dummy which the assembler
4618: put out, but there are no symbols in it, skip it now. */
4619: if (orig_sym_hdr.ifdMax > 1
4620: && orig_files->csym == 2
4621: && orig_files->caux == 0)
4622: {
4623: char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
1.1.1.4 root 4624: char *suffix = local_rindex (filename, '.');
1.1 root 4625:
4626: if (suffix != (char *)0 && strcmp (suffix, ".s") == 0)
4627: delete_ifd = 1;
4628: }
4629:
4630:
4631: /* Create array to map original file numbers to the new file numbers
4632: (in case there are duplicate filenames, we collapse them into one
4633: file section, the MIPS assembler may or may not collapse them). */
4634:
4635: remap_file_number = (int *) alloca (sizeof (int) * orig_sym_hdr.ifdMax);
4636:
4637: for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4638: {
4639: register FDR *fd_ptr = ORIG_FILES (fd);
4640: register char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4641:
4642: /* file support itself. */
4643: add_file (filename, filename + strlen (filename));
4644: remap_file_number[fd] = cur_file_ptr->file_index;
4645: }
4646:
4647: if (delete_ifd > 0) /* just in case */
4648: remap_file_number[0] = remap_file_number[1];
4649:
4650:
4651: /* Loop, adding each of the external symbols. These must be in
4652: order or otherwise we would have to change the relocation
4653: entries. We don't just call add_bytes, because we need to have
4654: the names put into the external hash table. We set the type to
4655: 'void' for now, and parse_def will fill in the correct type if it
4656: is in the symbol table. We must add the external symbols before
4657: the locals, since the locals do lookups against the externals. */
4658:
4659: if (debug)
4660: fprintf (stderr, "\tehash\n");
4661:
4662: for (es = 0; es < orig_sym_hdr.iextMax; es++)
4663: {
4664: register EXTR *eptr = orig_ext_syms + es;
4665: register char *ename = ORIG_ESTRS (eptr->asym.iss);
4666: register unsigned ifd = eptr->ifd;
4667:
4668: (void) add_ext_symbol (ename,
4669: ename + strlen (ename),
4670: (st_t) eptr->asym.st,
4671: (sc_t) eptr->asym.sc,
4672: eptr->asym.value,
4673: (symint_t)((eptr->asym.index == indexNil) ? indexNil : 0),
4674: (ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
4675: }
4676:
4677:
4678: /* For each of the files in the object file, copy the symbols, and such
4679: into the varrays for the new object file. */
4680:
4681: for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
4682: {
4683: register FDR *fd_ptr = ORIG_FILES (fd);
4684: register char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
4685: register SYMR *sym_start;
4686: register SYMR *sym;
4687: register SYMR *sym_end_p1;
4688: register PDR *proc_start;
4689: register PDR *proc;
4690: register PDR *proc_end_p1;
4691:
4692: /* file support itself. */
4693: add_file (filename, filename + strlen (filename));
4694: cur_file_ptr->orig_fdr = fd_ptr;
4695:
4696: /* Copy stuff that's just passed through (such as line #'s) */
4697: cur_file_ptr->fdr.adr = fd_ptr->adr;
4698: cur_file_ptr->fdr.ilineBase = fd_ptr->ilineBase;
4699: cur_file_ptr->fdr.cline = fd_ptr->cline;
4700: cur_file_ptr->fdr.rfdBase = fd_ptr->rfdBase;
4701: cur_file_ptr->fdr.crfd = fd_ptr->crfd;
4702: cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
4703: cur_file_ptr->fdr.cbLine = fd_ptr->cbLine;
4704: cur_file_ptr->fdr.fMerge = fd_ptr->fMerge;
4705: cur_file_ptr->fdr.fReadin = fd_ptr->fReadin;
4706: cur_file_ptr->fdr.glevel = fd_ptr->glevel;
4707:
4708: if (debug)
4709: fprintf (stderr, "\thash\tstart, filename %s\n", filename);
4710:
4711: /* For each of the static and global symbols defined, add them
4712: to the hash table of original symbols, so we can look up
4713: their values. */
4714:
4715: sym_start = ORIG_LSYMS (fd_ptr->isymBase);
4716: sym_end_p1 = sym_start + fd_ptr->csym;
4717: for (sym = sym_start; sym < sym_end_p1; sym++)
4718: {
4719: switch ((st_t) sym->st)
4720: {
4721: default:
4722: break;
4723:
4724: case st_Global:
4725: case st_Static:
4726: case st_Label:
4727: case st_Proc:
4728: case st_StaticProc:
4729: {
4730: auto symint_t hash_index;
4731: register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4732: register Size_t len = strlen (str);
4733: register shash_t *shash_ptr = hash_string (str,
4734: (Ptrdiff_t)len,
4735: &orig_str_hash[0],
4736: &hash_index);
4737:
4738: if (shash_ptr != (shash_t *)0)
4739: error ("internal error, %s is already in original symbol table", str);
4740:
4741: else
4742: {
4743: shash_ptr = allocate_shash ();
4744: shash_ptr->next = orig_str_hash[hash_index];
4745: orig_str_hash[hash_index] = shash_ptr;
4746:
4747: shash_ptr->len = len;
1.1.1.4 root 4748: shash_ptr->indx = indexNil;
1.1 root 4749: shash_ptr->string = str;
4750: shash_ptr->sym_ptr = sym;
4751: }
4752: }
4753: break;
4754:
4755: case st_End:
4756: if ((sc_t) sym->sc == sc_Text)
4757: {
4758: register char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
4759:
4760: if (*str != '\0')
4761: {
4762: register Size_t len = strlen (str);
4763: register shash_t *shash_ptr = hash_string (str,
4764: (Ptrdiff_t)len,
4765: &orig_str_hash[0],
4766: (symint_t *)0);
4767:
4768: if (shash_ptr != (shash_t *)0)
4769: shash_ptr->end_ptr = sym;
4770: }
4771: }
4772: break;
4773:
4774: }
4775: }
4776:
4777: if (debug)
4778: {
4779: fprintf (stderr, "\thash\tdone, filename %s\n", filename);
4780: fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
4781: }
4782:
4783: /* Go through each of the procedures in this file, and add the
4784: procedure pointer to the hash entry for the given name. */
4785:
4786: proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
4787: proc_end_p1 = proc_start + fd_ptr->cpd;
4788: for (proc = proc_start; proc < proc_end_p1; proc++)
4789: {
4790: register SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
4791: register char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
4792: register Size_t len = strlen (str);
4793: register shash_t *shash_ptr = hash_string (str,
4794: (Ptrdiff_t)len,
4795: &orig_str_hash[0],
4796: (symint_t *)0);
4797:
4798: if (shash_ptr == (shash_t *)0)
4799: error ("internal error, function %s is not in original symbol table", str);
4800:
4801: else
4802: shash_ptr->proc_ptr = proc;
4803: }
4804:
4805: if (debug)
4806: fprintf (stderr, "\tproc\tdone, filename %s\n", filename);
4807:
4808: }
4809: cur_file_ptr = first_file;
4810:
4811:
4812: /* Copy all of the object file up to the symbol table. Originally
4813: we were going to use ftruncate, but that doesn't seem to work
4814: on Ultrix 3.1.... */
4815:
4816: if (fseek (obj_in_stream, (long)0, SEEK_SET) != 0)
4817: pfatal_with_name (obj_in_name);
4818:
4819: if (fseek (object_stream, (long)0, SEEK_SET) != 0)
4820: pfatal_with_name (object_name);
4821:
4822: for (remaining = orig_file_header.f_symptr;
4823: remaining > 0;
4824: remaining -= num_write)
4825: {
4826: num_write = (remaining <= sizeof (buffer)) ? remaining : sizeof (buffer);
4827: sys_read = fread ((PTR_T) buffer, 1, num_write, obj_in_stream);
4828: if (sys_read <= 0)
4829: pfatal_with_name (obj_in_name);
4830:
4831: else if (sys_read != num_write)
4832: fatal ("Wanted to read %d bytes from %s, system returned %d",
4833: num_write,
4834: obj_in_name,
4835: sys_read);
4836:
4837: sys_write = fwrite (buffer, 1, num_write, object_stream);
4838: if (sys_write <= 0)
4839: pfatal_with_name (object_name);
4840:
4841: else if (sys_write != num_write)
4842: fatal ("Wrote %d bytes to %s, system returned %d",
4843: num_write,
4844: object_name,
4845: sys_write);
4846: }
4847: }
4848:
4849:
4850: /* Ye olde main program. */
4851:
4852: int
4853: main (argc, argv)
4854: int argc;
4855: char *argv[];
4856: {
4857: int iflag = 0;
1.1.1.4 root 4858: char *p = local_rindex (argv[0], '/');
1.1 root 4859: char *num_end;
4860: int option;
4861: int i;
4862:
4863: progname = (p != 0) ? p+1 : argv[0];
4864:
4865: (void) signal (SIGSEGV, catch_signal);
4866: (void) signal (SIGBUS, catch_signal);
4867: (void) signal (SIGABRT, catch_signal);
4868:
4869: #if !defined(__SABER__) && !defined(lint)
4870: if (sizeof (efdr_t) > PAGE_USIZE)
4871: fatal ("Efdr_t has a sizeof %d bytes, when it should be less than %d",
4872: sizeof (efdr_t),
4873: PAGE_USIZE);
4874:
4875: if (sizeof (page_t) != PAGE_USIZE)
4876: fatal ("Page_t has a sizeof %d bytes, when it should be %d",
4877: sizeof (page_t),
4878: PAGE_USIZE);
4879:
4880: #endif
4881:
4882: alloc_counts[ alloc_type_none ].alloc_name = "none";
4883: alloc_counts[ alloc_type_scope ].alloc_name = "scope";
4884: alloc_counts[ alloc_type_vlinks ].alloc_name = "vlinks";
4885: alloc_counts[ alloc_type_shash ].alloc_name = "shash";
4886: alloc_counts[ alloc_type_thash ].alloc_name = "thash";
4887: alloc_counts[ alloc_type_tag ].alloc_name = "tag";
4888: alloc_counts[ alloc_type_forward ].alloc_name = "forward";
4889: alloc_counts[ alloc_type_thead ].alloc_name = "thead";
4890: alloc_counts[ alloc_type_varray ].alloc_name = "varray";
4891:
4892: int_type_info = type_info_init;
4893: int_type_info.basic_type = bt_Int;
4894:
4895: void_type_info = type_info_init;
4896: void_type_info.basic_type = bt_Void;
4897:
4898: while ((option = getopt (argc, argv, "d:i:I:o:v")) != EOF)
4899: switch (option)
4900: {
4901: default:
4902: had_errors++;
4903: break;
4904:
4905: case 'd':
4906: debug = strtol (optarg, &num_end, 0);
4907: if ((unsigned)debug > 4 || num_end == optarg)
4908: had_errors++;
4909:
4910: break;
4911:
4912: case 'I':
4913: if (rename_output || obj_in_name != (char *)0)
4914: had_errors++;
4915: else
4916: rename_output = 1;
4917:
4918: /* fall through to 'i' case. */
4919:
4920: case 'i':
4921: if (obj_in_name == (char *)0)
4922: {
4923: obj_in_name = optarg;
4924: iflag++;
4925: }
4926: else
4927: had_errors++;
4928: break;
4929:
4930: case 'o':
4931: if (object_name == (char *)0)
4932: object_name = optarg;
4933: else
4934: had_errors++;
4935: break;
4936:
4937: case 'v':
4938: version++;
4939: break;
4940: }
4941:
4942: if (obj_in_name == (char *)0 && optind <= argc - 2)
4943: obj_in_name = argv[--argc];
4944:
4945: if (object_name == (char *)0 && optind <= argc - 2)
4946: object_name = argv[--argc];
4947:
4948: /* If there is an output name, but no input name use
4949: the same file for both, deleting the name between
4950: opening it for input and opening it for output. */
4951: if (obj_in_name == (char *)0 && object_name != (char *)0)
4952: {
4953: obj_in_name = object_name;
4954: delete_input = 1;
4955: }
4956:
4957: if (object_name == (char *)0 || had_errors || optind != argc - 1)
4958: {
4959: fprintf (stderr, "Calling Sequence:\n");
4960: fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4961: fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n");
4962: fprintf (stderr, "\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n");
4963: fprintf (stderr, "\n");
4964: fprintf (stderr, "Debug levels are:\n");
4965: fprintf (stderr, " 1\tGeneral debug + trace functions/blocks.\n");
4966: fprintf (stderr, " 2\tDebug level 1 + trace externals.\n");
4967: fprintf (stderr, " 3\tDebug level 2 + trace all symbols.\n");
4968: fprintf (stderr, " 4\tDebug level 3 + trace memory allocations.\n");
4969: return 1;
4970: }
4971:
4972:
4973: if (version)
4974: {
4975: fprintf (stderr, "mips-tfile version %s", version_string);
4976: #ifdef TARGET_VERSION
4977: TARGET_VERSION;
4978: #endif
4979: fputc ('\n', stderr);
4980: }
4981:
4982: if (obj_in_name == (char *)0)
4983: obj_in_name = object_name;
4984:
4985: if (rename_output && rename (object_name, obj_in_name) != 0)
4986: {
4987: char *buffer = (char *) allocate_multiple_pages (4);
4988: int len;
4989: int len2;
4990: int in_fd;
4991: int out_fd;
4992:
4993: /* Rename failed, copy input file */
4994: in_fd = open (object_name, O_RDONLY, 0666);
4995: if (in_fd < 0)
4996: pfatal_with_name (object_name);
4997:
4998: out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
4999: if (out_fd < 0)
5000: pfatal_with_name (obj_in_name);
5001:
5002: while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
5003: {
5004: len2 = write (out_fd, buffer, len);
5005: if (len2 < 0)
5006: pfatal_with_name (object_name);
5007:
5008: if (len != len2)
5009: fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
5010: }
5011:
5012: free_multiple_pages ((page_t *)buffer, 4);
5013:
5014: if (len < 0)
5015: pfatal_with_name (object_name);
5016:
5017: if (close (in_fd) < 0)
5018: pfatal_with_name (object_name);
5019:
5020: if (close (out_fd) < 0)
5021: pfatal_with_name (obj_in_name);
5022: }
5023:
5024: /* Must open input before output, since the output may be the same file, and
5025: we need to get the input handle before truncating it. */
5026: obj_in_stream = fopen (obj_in_name, "r");
5027: if (obj_in_stream == (FILE *)0)
5028: pfatal_with_name (obj_in_name);
5029:
5030: if (delete_input && unlink (obj_in_name) != 0)
5031: pfatal_with_name (obj_in_name);
5032:
5033: object_stream = fopen (object_name, "w");
5034: if (object_stream == (FILE *)0)
5035: pfatal_with_name (object_name);
5036:
5037: if (strcmp (argv[optind], "-") != 0)
5038: {
5039: input_name = argv[optind];
5040: if (freopen (argv[optind], "r", stdin) != stdin)
5041: pfatal_with_name (argv[optind]);
5042: }
5043:
5044: copy_object (); /* scan & copy object file */
5045: parse_input (); /* scan all of input */
5046:
5047: update_headers (); /* write out tfile */
5048: write_object ();
5049:
5050: if (debug)
5051: {
5052: fprintf (stderr, "\n\tAllocation summary:\n\n");
5053: for (i = (int)alloc_type_none; i < (int)alloc_type_last; i++)
5054: if (alloc_counts[i].total_alloc)
5055: {
5056: fprintf (stderr,
5057: "\t%s\t%5d allocation(s), %5d free(s), %2d page(s)\n",
5058: alloc_counts[i].alloc_name,
5059: alloc_counts[i].total_alloc,
5060: alloc_counts[i].total_free,
5061: alloc_counts[i].total_pages);
5062: }
5063: }
5064:
5065: return (had_errors) ? 1 : 0;
5066: }
5067:
5068:
5069: /* Catch a signal and exit without dumping core. */
5070:
5071: STATIC void
5072: catch_signal (signum)
5073: int signum;
5074: {
5075: (void) signal (signum, SIG_DFL); /* just in case... */
1.1.1.7 root 5076: #ifdef NO_SYS_SIGLIST
5077: fatal ("caught signal");
5078: #else
1.1 root 5079: fatal (sys_siglist[signum]);
1.1.1.7 root 5080: #endif
1.1 root 5081: }
5082:
5083: /* Print a fatal error message. NAME is the text.
5084: Also include a system error message based on `errno'. */
5085:
5086: void
5087: pfatal_with_name (msg)
5088: char *msg;
5089: {
5090: int save_errno = errno; /* just in case.... */
5091: if (line_number > 0)
5092: fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5093: else
5094: fprintf (stderr, "%s:", progname);
5095:
5096: errno = save_errno;
5097: if (errno == 0)
5098: fprintf (stderr, "[errno = 0] %s\n", msg);
5099: else
5100: perror (msg);
5101:
5102: exit (1);
5103: }
5104:
5105:
5106: /* Procedure to abort with an out of bounds error message. It has
5107: type int, so it can be used with an ?: expression within the
5108: ORIG_xxx macros, but the function never returns. */
5109:
5110: static int
1.1.1.4 root 5111: out_of_bounds (indx, max, str, prog_line)
5112: symint_t indx; /* index that is out of bounds */
1.1 root 5113: symint_t max; /* maximum index */
5114: const char *str; /* string to print out */
5115: int prog_line; /* line number within mips-tfile.c */
5116: {
1.1.1.4 root 5117: if (indx < max) /* just in case */
1.1 root 5118: return 0;
5119:
5120: fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n",
1.1.1.4 root 5121: progname, input_name, line_number, indx, str, max, prog_line);
1.1 root 5122:
5123: exit (1);
5124: return 0; /* turn off warning messages */
5125: }
5126:
5127:
5128: /* Allocate a cluster of pages. USE_MALLOC says that malloc does not
5129: like sbrk's behind it's back (or sbrk isn't available). If we use
5130: sbrk, we assume it gives us zeroed pages. */
5131:
5132: #ifndef MALLOC_CHECK
5133: #ifdef USE_MALLOC
5134:
5135: STATIC page_t *
5136: allocate_cluster (npages)
5137: Size_t npages;
5138: {
5139: register page_t *value = (page_t *) calloc (npages, PAGE_USIZE);
5140:
5141: if (value == 0)
5142: fatal ("Virtual memory exhausted.");
5143:
5144: if (debug > 3)
5145: fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
5146:
5147: return value;
5148: }
5149:
5150: #else /* USE_MALLOC */
5151:
5152: STATIC page_t *
5153: allocate_cluster (npages)
5154: Size_t npages;
5155: {
5156: register page_t *ptr = (page_t *) sbrk (0); /* current sbreak */
5157: unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
5158:
5159: if (offset != 0) /* align to a page boundary */
5160: {
5161: if (sbrk (PAGE_USIZE - offset) == (char *)-1)
5162: pfatal_with_name ("allocate_cluster");
5163:
5164: ptr = (page_t *) (((char *)ptr) + PAGE_SIZE - offset);
5165: }
5166:
5167: if (sbrk (npages * PAGE_USIZE) == (char *)-1)
5168: pfatal_with_name ("allocate_cluster");
5169:
5170: if (debug > 3)
5171: fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, ptr);
5172:
5173: return ptr;
5174: }
5175:
5176: #endif /* USE_MALLOC */
5177:
5178:
5179: static page_t *cluster_ptr = NULL;
5180: static unsigned pages_left = 0;
5181:
5182: #endif /* MALLOC_CHECK */
5183:
5184:
5185: /* Allocate some pages (which is initialized to 0). */
5186:
5187: STATIC page_t *
5188: allocate_multiple_pages (npages)
5189: Size_t npages;
5190: {
5191: #ifndef MALLOC_CHECK
5192: if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
5193: {
5194: pages_left = MAX_CLUSTER_PAGES;
5195: cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5196: }
5197:
5198: if (npages <= pages_left)
5199: {
5200: page_t *ptr = cluster_ptr;
5201: cluster_ptr += npages;
5202: pages_left -= npages;
5203: return ptr;
5204: }
5205:
5206: return allocate_cluster (npages);
5207:
5208: #else /* MALLOC_CHECK */
5209: return (page_t *) xcalloc (npages, PAGE_SIZE);
5210:
5211: #endif /* MALLOC_CHECK */
5212: }
5213:
5214:
5215: /* Release some pages. */
5216:
5217: STATIC void
5218: free_multiple_pages (page_ptr, npages)
5219: page_t *page_ptr;
5220: Size_t npages;
5221: {
5222: #ifndef MALLOC_CHECK
5223: if (pages_left == 0)
5224: {
5225: cluster_ptr = page_ptr;
5226: pages_left = npages;
5227: }
5228:
5229: else if ((page_ptr + npages) == cluster_ptr)
5230: {
5231: cluster_ptr -= npages;
5232: pages_left += npages;
5233: }
5234:
5235: /* otherwise the page is not freed. If more than call is
5236: done, we probably should worry about it, but at present,
5237: the free pages is done right after an allocate. */
5238:
5239: #else /* MALLOC_CHECK */
5240: free ((char *) page_ptr);
5241:
5242: #endif /* MALLOC_CHECK */
5243: }
5244:
5245:
5246: /* Allocate one page (which is initialized to 0). */
5247:
5248: STATIC page_t *
5249: allocate_page __proto((void))
5250: {
5251: #ifndef MALLOC_CHECK
5252: if (pages_left == 0)
5253: {
5254: pages_left = MAX_CLUSTER_PAGES;
5255: cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
5256: }
5257:
5258: pages_left--;
5259: return cluster_ptr++;
5260:
5261: #else /* MALLOC_CHECK */
5262: return (page_t *) xcalloc (1, PAGE_SIZE);
5263:
5264: #endif /* MALLOC_CHECK */
5265: }
5266:
5267:
5268: /* Allocate scoping information. */
5269:
5270: STATIC scope_t *
5271: allocate_scope __proto((void))
5272: {
5273: register scope_t *ptr;
5274: static scope_t initial_scope;
5275:
5276: #ifndef MALLOC_CHECK
5277: ptr = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
5278: if (ptr != (scope_t *)0)
5279: alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
5280:
5281: else
5282: {
5283: register int unallocated = alloc_counts[ (int)alloc_type_scope ].unallocated;
5284: register page_t *cur_page = alloc_counts[ (int)alloc_type_scope ].cur_page;
5285:
5286: if (unallocated == 0)
5287: {
5288: unallocated = PAGE_SIZE / sizeof (scope_t);
5289: alloc_counts[ (int)alloc_type_scope ].cur_page = cur_page = allocate_page ();
5290: alloc_counts[ (int)alloc_type_scope ].total_pages++;
5291: }
5292:
5293: ptr = &cur_page->scope[ --unallocated ];
5294: alloc_counts[ (int)alloc_type_scope ].unallocated = unallocated;
5295: }
5296:
5297: #else
5298: ptr = (scope_t *) xmalloc (sizeof (scope_t));
5299:
5300: #endif
5301:
5302: alloc_counts[ (int)alloc_type_scope ].total_alloc++;
5303: *ptr = initial_scope;
5304: return ptr;
5305: }
5306:
5307: /* Free scoping information. */
5308:
5309: STATIC void
5310: free_scope (ptr)
5311: scope_t *ptr;
5312: {
5313: alloc_counts[ (int)alloc_type_scope ].total_free++;
5314:
5315: #ifndef MALLOC_CHECK
5316: ptr->free = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
5317: alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr;
5318:
5319: #else
5320: xfree ((PTR_T) ptr);
5321: #endif
5322:
5323: }
5324:
5325:
5326: /* Allocate links for pages in a virtual array. */
5327:
5328: STATIC vlinks_t *
5329: allocate_vlinks __proto((void))
5330: {
5331: register vlinks_t *ptr;
5332: static vlinks_t initial_vlinks;
5333:
5334: #ifndef MALLOC_CHECK
5335: register int unallocated = alloc_counts[ (int)alloc_type_vlinks ].unallocated;
5336: register page_t *cur_page = alloc_counts[ (int)alloc_type_vlinks ].cur_page;
5337:
5338: if (unallocated == 0)
5339: {
5340: unallocated = PAGE_SIZE / sizeof (vlinks_t);
5341: alloc_counts[ (int)alloc_type_vlinks ].cur_page = cur_page = allocate_page ();
5342: alloc_counts[ (int)alloc_type_vlinks ].total_pages++;
5343: }
5344:
5345: ptr = &cur_page->vlinks[ --unallocated ];
5346: alloc_counts[ (int)alloc_type_vlinks ].unallocated = unallocated;
5347:
5348: #else
5349: ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
5350:
5351: #endif
5352:
5353: alloc_counts[ (int)alloc_type_vlinks ].total_alloc++;
5354: *ptr = initial_vlinks;
5355: return ptr;
5356: }
5357:
5358:
5359: /* Allocate string hash buckets. */
5360:
5361: STATIC shash_t *
5362: allocate_shash __proto((void))
5363: {
5364: register shash_t *ptr;
5365: static shash_t initial_shash;
5366:
5367: #ifndef MALLOC_CHECK
5368: register int unallocated = alloc_counts[ (int)alloc_type_shash ].unallocated;
5369: register page_t *cur_page = alloc_counts[ (int)alloc_type_shash ].cur_page;
5370:
5371: if (unallocated == 0)
5372: {
5373: unallocated = PAGE_SIZE / sizeof (shash_t);
5374: alloc_counts[ (int)alloc_type_shash ].cur_page = cur_page = allocate_page ();
5375: alloc_counts[ (int)alloc_type_shash ].total_pages++;
5376: }
5377:
5378: ptr = &cur_page->shash[ --unallocated ];
5379: alloc_counts[ (int)alloc_type_shash ].unallocated = unallocated;
5380:
5381: #else
5382: ptr = (shash_t *) xmalloc (sizeof (shash_t));
5383:
5384: #endif
5385:
5386: alloc_counts[ (int)alloc_type_shash ].total_alloc++;
5387: *ptr = initial_shash;
5388: return ptr;
5389: }
5390:
5391:
5392: /* Allocate type hash buckets. */
5393:
5394: STATIC thash_t *
5395: allocate_thash __proto((void))
5396: {
5397: register thash_t *ptr;
5398: static thash_t initial_thash;
5399:
5400: #ifndef MALLOC_CHECK
5401: register int unallocated = alloc_counts[ (int)alloc_type_thash ].unallocated;
5402: register page_t *cur_page = alloc_counts[ (int)alloc_type_thash ].cur_page;
5403:
5404: if (unallocated == 0)
5405: {
5406: unallocated = PAGE_SIZE / sizeof (thash_t);
5407: alloc_counts[ (int)alloc_type_thash ].cur_page = cur_page = allocate_page ();
5408: alloc_counts[ (int)alloc_type_thash ].total_pages++;
5409: }
5410:
5411: ptr = &cur_page->thash[ --unallocated ];
5412: alloc_counts[ (int)alloc_type_thash ].unallocated = unallocated;
5413:
5414: #else
5415: ptr = (thash_t *) xmalloc (sizeof (thash_t));
5416:
5417: #endif
5418:
5419: alloc_counts[ (int)alloc_type_thash ].total_alloc++;
5420: *ptr = initial_thash;
5421: return ptr;
5422: }
5423:
5424:
5425: /* Allocate structure, union, or enum tag information. */
5426:
5427: STATIC tag_t *
5428: allocate_tag __proto((void))
5429: {
5430: register tag_t *ptr;
5431: static tag_t initial_tag;
5432:
5433: #ifndef MALLOC_CHECK
5434: ptr = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
5435: if (ptr != (tag_t *)0)
5436: alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr->free;
5437:
5438: else
5439: {
5440: register int unallocated = alloc_counts[ (int)alloc_type_tag ].unallocated;
5441: register page_t *cur_page = alloc_counts[ (int)alloc_type_tag ].cur_page;
5442:
5443: if (unallocated == 0)
5444: {
5445: unallocated = PAGE_SIZE / sizeof (tag_t);
5446: alloc_counts[ (int)alloc_type_tag ].cur_page = cur_page = allocate_page ();
5447: alloc_counts[ (int)alloc_type_tag ].total_pages++;
5448: }
5449:
5450: ptr = &cur_page->tag[ --unallocated ];
5451: alloc_counts[ (int)alloc_type_tag ].unallocated = unallocated;
5452: }
5453:
5454: #else
5455: ptr = (tag_t *) xmalloc (sizeof (tag_t));
5456:
5457: #endif
5458:
5459: alloc_counts[ (int)alloc_type_tag ].total_alloc++;
5460: *ptr = initial_tag;
5461: return ptr;
5462: }
5463:
5464: /* Free scoping information. */
5465:
5466: STATIC void
5467: free_tag (ptr)
5468: tag_t *ptr;
5469: {
5470: alloc_counts[ (int)alloc_type_tag ].total_free++;
5471:
5472: #ifndef MALLOC_CHECK
5473: ptr->free = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
5474: alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr;
5475:
5476: #else
5477: xfree ((PTR_T) ptr);
5478: #endif
5479:
5480: }
5481:
5482:
5483: /* Allocate forward reference to a yet unknown tag. */
5484:
5485: STATIC forward_t *
5486: allocate_forward __proto((void))
5487: {
5488: register forward_t *ptr;
5489: static forward_t initial_forward;
5490:
5491: #ifndef MALLOC_CHECK
5492: ptr = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
5493: if (ptr != (forward_t *)0)
5494: alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr->free;
5495:
5496: else
5497: {
5498: register int unallocated = alloc_counts[ (int)alloc_type_forward ].unallocated;
5499: register page_t *cur_page = alloc_counts[ (int)alloc_type_forward ].cur_page;
5500:
5501: if (unallocated == 0)
5502: {
5503: unallocated = PAGE_SIZE / sizeof (forward_t);
5504: alloc_counts[ (int)alloc_type_forward ].cur_page = cur_page = allocate_page ();
5505: alloc_counts[ (int)alloc_type_forward ].total_pages++;
5506: }
5507:
5508: ptr = &cur_page->forward[ --unallocated ];
5509: alloc_counts[ (int)alloc_type_forward ].unallocated = unallocated;
5510: }
5511:
5512: #else
5513: ptr = (forward_t *) xmalloc (sizeof (forward_t));
5514:
5515: #endif
5516:
5517: alloc_counts[ (int)alloc_type_forward ].total_alloc++;
5518: *ptr = initial_forward;
5519: return ptr;
5520: }
5521:
5522: /* Free scoping information. */
5523:
5524: STATIC void
5525: free_forward (ptr)
5526: forward_t *ptr;
5527: {
5528: alloc_counts[ (int)alloc_type_forward ].total_free++;
5529:
5530: #ifndef MALLOC_CHECK
5531: ptr->free = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
5532: alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr;
5533:
5534: #else
5535: xfree ((PTR_T) ptr);
5536: #endif
5537:
5538: }
5539:
5540:
5541: /* Allocate head of type hash list. */
5542:
5543: STATIC thead_t *
5544: allocate_thead __proto((void))
5545: {
5546: register thead_t *ptr;
5547: static thead_t initial_thead;
5548:
5549: #ifndef MALLOC_CHECK
5550: ptr = alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
5551: if (ptr != (thead_t *)0)
5552: alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
5553:
5554: else
5555: {
5556: register int unallocated = alloc_counts[ (int)alloc_type_thead ].unallocated;
5557: register page_t *cur_page = alloc_counts[ (int)alloc_type_thead ].cur_page;
5558:
5559: if (unallocated == 0)
5560: {
5561: unallocated = PAGE_SIZE / sizeof (thead_t);
5562: alloc_counts[ (int)alloc_type_thead ].cur_page = cur_page = allocate_page ();
5563: alloc_counts[ (int)alloc_type_thead ].total_pages++;
5564: }
5565:
5566: ptr = &cur_page->thead[ --unallocated ];
5567: alloc_counts[ (int)alloc_type_thead ].unallocated = unallocated;
5568: }
5569:
5570: #else
5571: ptr = (thead_t *) xmalloc (sizeof (thead_t));
5572:
5573: #endif
5574:
5575: alloc_counts[ (int)alloc_type_thead ].total_alloc++;
5576: *ptr = initial_thead;
5577: return ptr;
5578: }
5579:
5580: /* Free scoping information. */
5581:
5582: STATIC void
5583: free_thead (ptr)
5584: thead_t *ptr;
5585: {
5586: alloc_counts[ (int)alloc_type_thead ].total_free++;
5587:
5588: #ifndef MALLOC_CHECK
5589: ptr->free = (thead_t *) alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
5590: alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr;
5591:
5592: #else
5593: xfree ((PTR_T) ptr);
5594: #endif
5595:
5596: }
5597:
1.1.1.4 root 5598: #endif /* MIPS_DEBUGGING_INFO */
1.1 root 5599:
5600:
1.1.1.7 root 5601: #ifdef HAVE_VPRINTF
5602:
1.1 root 5603: /* Output an error message and exit */
5604:
5605: /*VARARGS*/
5606: void
1.1.1.8 ! root 5607: fatal VPROTO((const char *format, ...))
1.1 root 5608: {
1.1.1.7 root 5609: #ifndef __STDC__
1.1 root 5610: char *format;
1.1.1.7 root 5611: #endif
5612: va_list ap;
5613:
5614: VA_START (ap, format);
5615:
5616: #ifndef __STDC__
5617: format = va_arg (ap, char*);
5618: #endif
1.1 root 5619:
5620: if (line_number > 0)
5621: fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5622: else
5623: fprintf (stderr, "%s:", progname);
5624:
5625: vfprintf (stderr, format, ap);
5626: va_end (ap);
5627: fprintf (stderr, "\n");
5628: if (line_number > 0)
5629: fprintf (stderr, "line:\t%s\n", cur_line_start);
5630:
5631: saber_stop ();
5632: exit (1);
5633: }
5634:
5635: /*VARARGS*/
5636: void
1.1.1.8 ! root 5637: error VPROTO((const char *format, ...))
1.1 root 5638: {
1.1.1.7 root 5639: #ifndef __STDC__
1.1 root 5640: char *format;
1.1.1.7 root 5641: #endif
5642: va_list ap;
5643:
5644: VA_START (ap, format);
5645:
5646: #ifndef __STDC__
5647: format = va_arg (ap, char*);
5648: #endif
1.1 root 5649:
5650: if (line_number > 0)
5651: fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
5652: else
5653: fprintf (stderr, "%s:", progname);
5654:
5655: vfprintf (stderr, format, ap);
5656: fprintf (stderr, "\n");
5657: if (line_number > 0)
5658: fprintf (stderr, "line:\t%s\n", cur_line_start);
5659:
5660: had_errors++;
5661: va_end (ap);
5662:
5663: saber_stop ();
5664: }
5665:
1.1.1.7 root 5666: #else /* not HAVE_VPRINTF */
5667:
5668: void
5669: fatal (msg, arg1, arg2)
5670: char *msg, *arg1, *arg2;
5671: {
5672: error (msg, arg1, arg2);
5673: exit (1);
5674: }
5675:
5676: void
5677: error (msg, arg1, arg2)
5678: char *msg, *arg1, *arg2;
5679: {
5680: fprintf (stderr, "%s: ", progname);
5681: fprintf (stderr, msg, arg1, arg2);
5682: fprintf (stderr, "\n");
5683: }
5684:
5685: #endif /* not HAVE_VPRINTF */
5686:
1.1 root 5687: /* More 'friendly' abort that prints the line and file.
5688: config.h can #define abort fancy_abort if you like that sort of thing. */
5689:
5690: void
5691: fancy_abort ()
5692: {
5693: fatal ("Internal abort.");
5694: }
5695:
5696:
5697: /* When `malloc.c' is compiled with `rcheck' defined,
5698: it calls this function to report clobberage. */
5699:
5700: void
5701: botch (s)
5702: const char *s;
5703: {
5704: fatal (s);
5705: }
5706:
5707: /* Same as `malloc' but report error if no memory available. */
5708:
5709: PTR_T
5710: xmalloc (size)
5711: Size_t size;
5712: {
5713: register PTR_T value = malloc (size);
5714: if (value == 0)
5715: fatal ("Virtual memory exhausted.");
5716:
5717: if (debug > 3)
5718: fprintf (stderr, "\tmalloc\tptr = 0x%.8x, size = %10u\n", value, size);
5719:
5720: return value;
5721: }
5722:
5723: /* Same as `calloc' but report error if no memory available. */
5724:
5725: PTR_T
5726: xcalloc (size1, size2)
5727: Size_t size1, size2;
5728: {
5729: register PTR_T value = calloc (size1, size2);
5730: if (value == 0)
5731: fatal ("Virtual memory exhausted.");
5732:
5733: if (debug > 3)
5734: fprintf (stderr, "\tcalloc\tptr = 0x%.8x, size1 = %10u, size2 = %10u [%u]\n",
5735: value, size1, size2, size1+size2);
5736:
5737: return value;
5738: }
5739:
5740: /* Same as `realloc' but report error if no memory available. */
5741:
5742: PTR_T
5743: xrealloc (ptr, size)
5744: PTR_T ptr;
5745: Size_t size;
5746: {
5747: register PTR_T result = realloc (ptr, size);
5748: if (!result)
5749: fatal ("Virtual memory exhausted.");
5750:
5751: if (debug > 3)
5752: fprintf (stderr, "\trealloc\tptr = 0x%.8x, size = %10u, orig = 0x%.8x\n",
5753: result, size, ptr);
5754:
5755: return result;
5756: }
5757:
5758: void
5759: xfree (ptr)
5760: PTR_T ptr;
5761: {
5762: if (debug > 3)
5763: fprintf (stderr, "\tfree\tptr = 0x%.8x\n", ptr);
5764:
5765: free (ptr);
5766: }
1.1.1.4 root 5767:
5768:
5769: /* Define our own index/rindex, since the local and global symbol
5770: structures as defined by MIPS has an 'index' field. */
5771:
5772: STATIC char *
5773: local_index (str, sentinel)
5774: const char *str;
5775: int sentinel;
5776: {
5777: int ch;
5778:
5779: for ( ; (ch = *str) != sentinel; str++)
5780: {
5781: if (ch == '\0')
5782: return (char *)0;
5783: }
5784:
5785: return (char *)str;
5786: }
5787:
5788: STATIC char *
5789: local_rindex (str, sentinel)
5790: const char *str;
5791: int sentinel;
5792: {
5793: int ch;
5794: const char *ret = (const char *)0;
5795:
5796: for ( ; (ch = *str) != '\0'; str++)
5797: {
5798: if (ch == sentinel)
5799: ret = str;
5800: }
5801:
5802: return (char *)ret;
5803: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.