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