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