1: 
  2: /*
  3:  * Copyright (c) 1986-1995 by Symantec
  4:  * Copyright (c) 2000-2009 by Digital Mars
  5:  * All Rights Reserved
  6:  * http://www.digitalmars.com
  7:  * Written by Walter Bright
  8:  *
  9:  * This source file is made available for personal use
 10:  * only. The license is in /dmd/src/dmd/backendlicense.txt
 11:  * For any other uses, please contact Digital Mars.
 12:  */
 13: 
 14: // Compiler implementation of the D programming language
 15: 
 16: #include <stdio.h>
 17: #include <stdlib.h>
 18: static char __file__[] = __FILE__;      /* for tassert.h                */
 19: #include        "tassert.h"
 20: 
 21: #include "rmem.h"
 22: #include "root.h"
 23: #include "stringtable.h"
 24: 
 25: #include "mars.h"
 26: #include "lib.h"
 27: 
 28: #define LOG 0
 29: 
 30: Library::Library()
 31: {
 32:     libfile = NULL;
 33: }
 34: 
 35: /***********************************
 36:  * Set the library file name based on the output directory
 37:  * and the filename.
 38:  * Add default library file name extension.
 39:  */
 40: 
 41: void Library::setFilename(char *dir, char *filename)
 42: {
 43:     char *arg = filename;
 44:     if (!arg || !*arg)
 45:     {   // Generate lib file name from first obj name
 46:         char *n = global.params.objfiles->tdata()[0];
 47: 
 48:         n = FileName::name(n);
 49:         FileName *fn = FileName::forceExt(n, global.lib_ext);
 50:         arg = fn->toChars();
 51:     }
 52:     if (!FileName::absolute(arg))
 53:         arg = FileName::combine(dir, arg);
 54:     FileName *libfilename = FileName::defaultExt(arg, global.lib_ext);
 55: 
 56:     libfile = new File(libfilename);
 57: }
 58: 
 59: void Library::write()
 60: {
 61:     if (global.params.verbose)
 62:         printf("library   %s\n", libfile->name->toChars());
 63: 
 64:     OutBuffer libbuf;
 65:     WriteLibToBuffer(&libbuf);
 66: 
 67:     // Transfer image to file
 68:     libfile->setbuffer(libbuf.data, libbuf.offset);
 69:     libbuf.extractData();
 70: 
 71: 
 72:     char *p = FileName::path(libfile->name->toChars());
 73:     FileName::ensurePathExists(p);
 74:     //mem.free(p);
 75: 
 76:     libfile->writev();
 77: }
 78: 
 79: /*****************************************************************************/
 80: 
 81: void Library::addLibrary(void *buf, size_t buflen)
 82: {
 83:     addObject(NULL, buf, buflen);
 84: }
 85: 
 86: 
 87: /*****************************************************************************/
 88: /*****************************************************************************/
 89: 
 90: /**************************
 91:  * Record types:
 92:  */
 93: 
 94: #define RHEADR  0x6E
 95: #define REGINT  0x70
 96: #define REDATA  0x72
 97: #define RIDATA  0x74
 98: #define OVLDEF  0x76
 99: #define ENDREC  0x78
100: #define BLKDEF  0x7A
101: #define BLKEND  0x7C
102: #define DEBSYM  0x7E
103: #define THEADR  0x80
104: #define LHEADR  0x82
105: #define PEDATA  0x84
106: #define PIDATA  0x86
107: #define COMENT  0x88
108: #define MODEND  0x8A
109: #define M386END 0x8B    /* 32 bit module end record */
110: #define EXTDEF  0x8C
111: #define TYPDEF  0x8E
112: #define PUBDEF  0x90
113: #define PUB386  0x91
114: #define LOCSYM  0x92
115: #define LINNUM  0x94
116: #define LNAMES  0x96
117: #define SEGDEF  0x98
118: #define GRPDEF  0x9A
119: #define FIXUPP  0x9C
120: /*#define (none)        0x9E    */
121: #define LEDATA  0xA0
122: #define LIDATA  0xA2
123: #define LIBHED  0xA4
124: #define LIBNAM  0xA6
125: #define LIBLOC  0xA8
126: #define LIBDIC  0xAA
127: #define COMDEF  0xB0
128: #define LEXTDEF 0xB4
129: #define LPUBDEF 0xB6
130: #define LCOMDEF 0xB8
131: #define CEXTDEF 0xBC
132: #define COMDAT  0xC2
133: #define LINSYM  0xC4
134: #define ALIAS   0xC6
135: #define LLNAMES 0xCA
136: 
137: 
138: #define LIBIDMAX (512 - 0x25 - 3 - 4)   // max size that will fit in dictionary
139: 
140: 
141: struct ObjModule
142: {
143:     unsigned char *base;        // where are we holding it in memory
144:     unsigned length;            // in bytes
145:     unsigned short page;        // page module starts in output file
146:     unsigned char flags;
147: #define MFgentheadr     1       // generate THEADR record
148: #define MFtheadr        2       // module name comes from THEADR record
149:     char *name;                 // module name
150: };
151: 
152: static void parseName(unsigned char **pp, char *name)
153: {
154:     unsigned char *p = *pp;
155:     unsigned len = *p++;
156:     if (len == 0xFF && *p == 0)  // if long name
157:     {
158:         len = p[1] & 0xFF;
159:         len |= (unsigned)p[2] << 8;
160:         p += 3;
161:         assert(len <= LIBIDMAX);
162:     }
163:     memcpy(name, p, len);
164:     name[len] = 0;
165:     *pp = p + len;
166: }
167: 
168: static unsigned short parseIdx(unsigned char **pp)
169: {
170:     unsigned char *p = *pp;
171:     unsigned char c = *p++;
172: 
173:     unsigned short idx = (0x80 & c) ? ((0x7F & c) << 8) + *p++ : c;
174:     *pp = p;
175:     return idx;
176: }
177: 
178: void Library::addSymbol(ObjModule *om, char *name, int pickAny)
179: {
180: #if LOG
181:     printf("Library::addSymbol(%s, %s, %d)\n", om->name, name, pickAny);
182: #endif
183:     StringValue *s = tab.insert(name, strlen(name));
184:     if (!s)
185:     {   // already in table
186:         if (!pickAny)
187:         {   s = tab.lookup(name, strlen(name));
188:             assert(s);
189:             ObjSymbol *os = (ObjSymbol *)s->ptrvalue;
190:             error("multiple definition of %s: %s and %s: %s",
191:                 om->name, name, os->om->name, os->name);
192:         }
193:     }
194:     else
195:     {
196:         ObjSymbol *os = new ObjSymbol();
197:         os->name = strdup(name);
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(238) : see declaration of 'strdup'
198: os->om = om; 199: s->ptrvalue = (void *)os; 200: 201: objsymbols.push(os); 202: } 203: } 204: 205: /************************************ 206: * Scan single object module for dictionary symbols. 207: * Send those symbols to Library::addSymbol(). 208: */ 209: 210: void Library::scanObjModule(ObjModule *om) 211: { int easyomf; 212: unsigned u; 213: unsigned char result = 0; 214: char name[LIBIDMAX + 1]; 215: 216: Strings names; 217: names.push(NULL); // don't use index 0 218: 219: assert(om); 220: easyomf = 0; // assume not EASY-OMF 221: unsigned char *pend = om->base + om->length; 222: 223: unsigned char *pnext; 224: for (unsigned char *p = om->base; 1; p = pnext) 225: { 226: assert(p < pend); 227: unsigned char recTyp = *p++; 228: unsigned short recLen = *(unsigned short *)p; 229: p += 2; 230: pnext = p + recLen; 231: recLen--; // forget the checksum 232: 233: switch (recTyp) 234: { 235: case LNAMES: 236: case LLNAMES: 237: while (p + 1 < pnext) 238: { 239: parseName(&p, name); 240: names.push(strdup(name));
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(238) : see declaration of 'strdup'
241: } 242: break; 243: 244: case PUBDEF: 245: if (easyomf) 246: recTyp = PUB386; // convert to MS format 247: case PUB386: 248: if (!(parseIdx(&p) | parseIdx(&p))) 249: p += 2; // skip seg, grp, frame 250: while (p + 1 < pnext) 251: { 252: parseName(&p, name); 253: p += (recTyp == PUBDEF) ? 2 : 4; // skip offset 254: parseIdx(&p); // skip type index 255: addSymbol(om, name); 256: } 257: break; 258: 259: case COMDAT: 260: if (easyomf) 261: recTyp = COMDAT+1; // convert to MS format 262: case COMDAT+1: 263: { 264: int pickAny = 0; 265: 266: if (*p++ & 5) // if continuation or local comdat 267: break; 268: 269: unsigned char attr = *p++; 270: if (attr & 0xF0) // attr: if multiple instances allowed 271: pickAny = 1; 272: p++; // align 273: 274: p += 2; // enum data offset 275: if (recTyp == COMDAT+1) 276: p += 2; // enum data offset 277: 278: parseIdx(&p); // type index 279: 280: if ((attr & 0x0F) == 0) // if explicit allocation 281: { parseIdx(&p); // base group 282: parseIdx(&p); // base segment 283: } 284: 285: unsigned idx = parseIdx(&p); // public name index 286: if( idx == 0 || idx >= names.dim) 287: { 288: //debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames)); 289: error("corrupt COMDAT"); 290: return; 291: } 292: 293: //printf("[s] name='%s'\n",name); 294: addSymbol(om, names.tdata()[idx],pickAny); 295: break; 296: } 297: case ALIAS: 298: while (p + 1 < pnext) 299: { 300: parseName(&p, name); 301: addSymbol(om, name); 302: parseName(&p, name); 303: } 304: break; 305: 306: case MODEND: 307: case M386END: 308: result = 1; 309: goto Ret; 310: 311: case COMENT: 312: // Recognize Phar Lap EASY-OMF format 313: { static unsigned char omfstr[7] = 314: {0x80,0xAA,'8','0','3','8','6'}; 315: 316: if (recLen == sizeof(omfstr)) 317: { 318: for (unsigned i = 0; i < sizeof(omfstr); i++) 319: if (*p++ != omfstr[i]) 320: goto L1; 321: easyomf = 1; 322: break; 323: L1: ; 324: } 325: } 326: // Recognize .IMPDEF Import Definition Records 327: { static unsigned char omfstr[] = 328: {0,0xA0,1}; 329: 330: if (recLen >= 7) 331: { 332: p++; 333: for (unsigned i = 1; i < sizeof(omfstr); i++) 334: if (*p++ != omfstr[i]) 335: goto L2; 336: p++; // skip OrdFlag field 337: parseName(&p, name); 338: addSymbol(om, name); 339: break; 340: L2: ; 341: } 342: } 343: break; 344: 345: default: 346: // ignore 347: ; 348: } 349: } 350: Ret: 351: for (u = 1; u < names.dim; u++) 352: free(names.tdata()[u]); 353: } 354: 355: /*************************************** 356: * Add object module or library to the library. 357: * Examine the buffer to see which it is. 358: * If the buffer is NULL, use module_name as the file name 359: * and load the file. 360: */ 361: 362: void Library::addObject(const char *module_name, void *buf, size_t buflen) 363: { 364: #if LOG 365: printf("Library::addObject(%s)\n", module_name ? module_name : ""); 366: #endif 367: if (!buf) 368: { assert(module_name); 369: FileName f((char *)module_name, 0); 370: File file(&f); 371: file.readv(); 372: buf = file.buffer; 373: buflen = file.len; 374: file.ref = 1; 375: } 376: 377: unsigned g_page_size; 378: unsigned char *pstart = (unsigned char *)buf; 379: int islibrary = 0; 380: 381: /* See if it's an OMF library. 382: * Don't go by file extension. 383: */ 384: 385: #pragma pack(1) 386: struct LibHeader 387: { 388: unsigned char recTyp; // 0xF0 389: unsigned short pagesize; 390: long lSymSeek; 391: unsigned short ndicpages; 392: unsigned char flags; 393: }; 394: #pragma pack() 395: 396: /* Determine if it is an OMF library, an OMF object module, 397: * or something else. 398: */ 399: if (buflen < sizeof(LibHeader)) 400: { 401: Lcorrupt: 402: error("corrupt object module"); 403: } 404: LibHeader *lh = (LibHeader *)buf; 405: if (lh->recTyp == 0xF0) 406: { /* OMF library 407: * The modules are all at buf[g_page_size .. lh->lSymSeek] 408: */ 409: islibrary = 1; 410: g_page_size = lh->pagesize + 3; 411: buf = (void *)(pstart + g_page_size); 412: if (lh->lSymSeek > buflen ||
warning C4018: '>' : signed/unsigned mismatch
413: g_page_size > buflen) 414: goto Lcorrupt; 415: buflen = lh->lSymSeek - g_page_size; 416: } 417: else if (lh->recTyp == '!' && memcmp(lh, "!<arch>\n", 8) == 0) 418: { 419: error("COFF libraries not supported"); 420: return; 421: } 422: else 423: { // Not a library, assume OMF object module 424: g_page_size = 16; 425: } 426: 427: /* Split up the buffer buf[0..buflen] into multiple object modules, 428: * each aligned on a g_page_size boundary. 429: */ 430: 431: ObjModule *om = NULL; 432: int first_module = 1; 433: 434: unsigned char *p = (unsigned char *)buf; 435: unsigned char *pend = p + buflen; 436: unsigned char *pnext; 437: for (; p < pend; p = pnext) // for each OMF record 438: { 439: if (p + 3 >= pend) 440: goto Lcorrupt; 441: unsigned char recTyp = *p; 442: unsigned short recLen = *(unsigned short *)(p + 1); 443: pnext = p + 3 + recLen; 444: if (pnext > pend) 445: goto Lcorrupt; 446: recLen--; /* forget the checksum */ 447: 448: switch (recTyp) 449: { 450: case LHEADR : 451: case THEADR : 452: if (!om) 453: { char name[LIBIDMAX + 1]; 454: om = new ObjModule(); 455: om->flags = 0; 456: om->base = p; 457: p += 3; 458: parseName(&p, name); 459: if (first_module && module_name && !islibrary) 460: { // Remove path and extension 461: om->name = strdup(FileName::name(module_name));
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(238) : see declaration of 'strdup'
462: char *ext = FileName::ext(om->name); 463: if (ext) 464: ext[-1] = 0; 465: } 466: else 467: { /* Use THEADR name as module name, 468: * removing path and extension. 469: */ 470: om->name = strdup(FileName::name(name));
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(238) : see declaration of 'strdup'
471: char *ext = FileName::ext(om->name); 472: if (ext) 473: ext[-1] = 0; 474: 475: om->flags |= MFtheadr; 476: } 477: if (strcmp(name, "C") == 0) // old C compilers did this 478: { om->flags |= MFgentheadr; // generate our own THEADR 479: om->base = pnext; // skip past THEADR 480: } 481: objmodules.push(om); 482: first_module = 0; 483: } 484: break; 485: 486: case MODEND : 487: case M386END: 488: { 489: if (om) 490: { om->page = (om->base - pstart) / g_page_size; 491: om->length = pnext - om->base; 492: om = NULL; 493: } 494: // Round up to next page 495: unsigned t = pnext - pstart; 496: t = (t + g_page_size - 1) & ~(unsigned)(g_page_size - 1); 497: pnext = pstart + t; 498: break; 499: } 500: default: 501: // ignore 502: ; 503: } 504: } 505: 506: if (om) 507: goto Lcorrupt; // missing MODEND record 508: } 509: 510: 511: /*****************************************************************************/ 512: /*****************************************************************************/ 513: 514: typedef int (__cdecl * cmpfunc_t)(const void *,const void *); 515: 516: extern "C" int NameCompare(ObjSymbol **p1, ObjSymbol **p2) 517: { 518: return strcmp((*p1)->name, (*p2)->name); 519: } 520: 521: #define HASHMOD 0x25 522: #define BUCKETPAGE 512 523: #define BUCKETSIZE (BUCKETPAGE - HASHMOD - 1) 524: 525: 526: /*********************************** 527: * Calculates number of pages needed for dictionary 528: * Returns: 529: * number of pages 530: */ 531: 532: unsigned short Library::numDictPages(unsigned padding) 533: { 534: unsigned short ndicpages; 535: unsigned short bucksForHash; 536: unsigned short bucksForSize; 537: unsigned symSize = 0; 538: 539: for (int i = 0; i < objsymbols.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
540: { ObjSymbol *s = objsymbols.tdata()[i]; 541: 542: symSize += ( strlen(s->name) + 4 ) & ~1; 543: } 544: 545: for (int i = 0; i < objmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
546: { ObjModule *om = objmodules.tdata()[i]; 547: 548: size_t len = strlen(om->name); 549: if (len > 0xFF) 550: len += 2; // Digital Mars long name extension 551: symSize += ( len + 4 + 1 ) & ~1; 552: } 553: 554: bucksForHash = (objsymbols.dim + objmodules.dim + HASHMOD - 3) / 555: (HASHMOD - 2); 556: bucksForSize = (symSize + BUCKETSIZE - padding - padding - 1) / 557: (BUCKETSIZE - padding); 558: 559: ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize; 560: //printf("ndicpages = %u\n",ndicpages); 561: 562: // Find prime number greater than ndicpages 563: static unsigned primes[] = 564: { 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43, 565: 47,53,59,61,67,71,73,79,83,89,97,101,103, 566: 107,109,113,127,131,137,139,149,151,157, 567: 163,167,173,179,181,191,193,197,199,211, 568: 223,227,229,233,239,241,251,257,263,269, 569: 271,277,281,283,293,307,311,313,317,331, 570: 337,347,349,353,359,367,373,379,383,389, 571: 397,401,409,419,421,431,433,439,443,449, 572: 457,461,463,467,479,487,491,499,503,509, 573: //521,523,541,547, 574: 0 575: }; 576: 577: for (int i = 0; 1; i++) 578: { 579: if ( primes[i] == 0 ) 580: { // Quick and easy way is out. 581: // Now try and find first prime number > ndicpages 582: unsigned prime; 583: 584: for (prime = (ndicpages + 1) | 1; 1; prime += 2) 585: { // Determine if prime is prime 586: for (unsigned u = 3; u < prime / 2; u += 2) 587: { 588: if ((prime / u) * u == prime) 589: goto L1; 590: } 591: break; 592: 593: L1: ; 594: } 595: ndicpages = prime; 596: break; 597: } 598: 599: if (primes[i] > ndicpages) 600: { 601: ndicpages = primes[i]; 602: break; 603: } 604: } 605: 606: return ndicpages; 607: } 608: 609: 610: /******************************************* 611: * Write a single entry into dictionary. 612: * Returns: 613: * 0 failure 614: */ 615: 616: static int EnterDict( unsigned char *bucketsP, unsigned short ndicpages, unsigned char *entry, unsigned entrylen ) 617: { 618: unsigned short uStartIndex; 619: unsigned short uStep; 620: unsigned short uStartPage; 621: unsigned short uPageStep; 622: unsigned short uIndex; 623: unsigned short uPage; 624: unsigned short n; 625: unsigned u; 626: unsigned nbytes; 627: unsigned char *aP; 628: unsigned char *zP; 629: 630: aP = entry; 631: zP = aP + entrylen; // point at last char in identifier 632: 633: uStartPage = 0; 634: uPageStep = 0; 635: uStartIndex = 0; 636: uStep = 0; 637: 638: u = entrylen; 639: while ( u-- ) 640: { 641: uStartPage = _rotl( uStartPage, 2 ) ^ ( *aP | 0x20 ); 642: uStep = _rotr( uStep, 2 ) ^ ( *aP++ | 0x20 ); 643: uStartIndex = _rotr( uStartIndex, 2 ) ^ ( *zP | 0x20 ); 644: uPageStep = _rotl( uPageStep, 2 ) ^ ( *zP-- | 0x20 ); 645: } 646: 647: uStartPage %= ndicpages; 648: uPageStep %= ndicpages; 649: if ( uPageStep == 0 ) 650: uPageStep++; 651: uStartIndex %= HASHMOD; 652: uStep %= HASHMOD; 653: if ( uStep == 0 ) 654: uStep++; 655: 656: uPage = uStartPage; 657: uIndex = uStartIndex; 658: 659: // number of bytes in entry 660: nbytes = 1 + entrylen + 2; 661: if (entrylen > 255) 662: nbytes += 2; 663: 664: while (1) 665: { 666: aP = &bucketsP[uPage * BUCKETPAGE]; 667: uStartIndex = uIndex; 668: while (1) 669: { 670: if ( 0 == aP[ uIndex ] ) 671: { 672: // n = next available position in this page 673: n = aP[ HASHMOD ] << 1; 674: assert(n > HASHMOD); 675: 676: // if off end of this page 677: if (n + nbytes > BUCKETPAGE ) 678: { aP[ HASHMOD ] = 0xFF; 679: break; // next page 680: } 681: else 682: { 683: aP[ uIndex ] = n >> 1; 684: memcpy( (aP + n), entry, nbytes ); 685: aP[ HASHMOD ] += (nbytes + 1) >> 1; 686: if (aP[HASHMOD] == 0) 687: aP[HASHMOD] = 0xFF; 688: return 1; 689: } 690: } 691: uIndex += uStep; 692: uIndex %= 0x25; 693: /*if (uIndex > 0x25) 694: uIndex -= 0x25;*/ 695: if( uIndex == uStartIndex ) 696: break; 697: } 698: uPage += uPageStep; 699: if (uPage >= ndicpages) 700: uPage -= ndicpages; 701: if( uPage == uStartPage ) 702: break; 703: } 704: 705: return 0; 706: } 707: 708: /******************************************* 709: * Write the module and symbol names to the dictionary. 710: * Returns: 711: * 0 failure 712: */ 713: 714: int Library::FillDict(unsigned char *bucketsP, unsigned short ndicpages) 715: { 716: unsigned char entry[4 + LIBIDMAX + 2 + 1]; 717: 718: //printf("FillDict()\n"); 719: 720: // Add each of the module names 721: for (int i = 0; i < objmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
722: { ObjModule *om = objmodules.tdata()[i]; 723: 724: unsigned short n = strlen( om->name ); 725: if (n > 255) 726: { entry[0] = 0xFF; 727: entry[1] = 0; 728: *(unsigned short *)(entry + 2) = n + 1; 729: memcpy(entry + 4, om->name, n); 730: n += 3; 731: } 732: else 733: { entry[ 0 ] = 1 + n; 734: memcpy(entry + 1, om->name, n ); 735: } 736: entry[ n + 1 ] = '!'; 737: *((unsigned short *)( n + 2 + entry )) = om->page; 738: if ( n & 1 ) 739: entry[ n + 2 + 2 ] = 0; 740: if ( !EnterDict( bucketsP, ndicpages, entry, n + 1 ) ) 741: return 0; 742: } 743: 744: // Sort the symbols 745: qsort( objsymbols.tdata(), objsymbols.dim, 4, (cmpfunc_t)NameCompare ); 746: 747: // Add each of the symbols 748: for (int i = 0; i < objsymbols.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
749: { ObjSymbol *os = objsymbols.tdata()[i]; 750: 751: unsigned short n = strlen( os->name ); 752: if (n > 255) 753: { entry[0] = 0xFF; 754: entry[1] = 0; 755: *(unsigned short *)(entry + 2) = n; 756: memcpy(entry + 4, os->name, n); 757: n += 3; 758: } 759: else 760: { entry[ 0 ] = n;
warning C4244: '=' : conversion from 'unsigned short' to 'unsigned char', possible loss of data
761: memcpy( entry + 1, os->name, n ); 762: } 763: *((unsigned short *)( n + 1 + entry )) = os->om->page; 764: if ( (n & 1) == 0 ) 765: entry[ n + 3] = 0; 766: if ( !EnterDict( bucketsP, ndicpages, entry, n ) ) 767: { 768: return 0; 769: } 770: } 771: return 1; 772: } 773: 774: 775: /********************************************** 776: * Create and write library to libbuf. 777: * The library consists of: 778: * library header 779: * object modules... 780: * dictionary header 781: * dictionary pages... 782: */ 783: 784: void Library::WriteLibToBuffer(OutBuffer *libbuf) 785: { 786: /* Scan each of the object modules for symbols 787: * to go into the dictionary 788: */ 789: for (int i = 0; i < objmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
790: { ObjModule *om = objmodules.tdata()[i]; 791: 792: scanObjModule(om); 793: } 794: 795: unsigned g_page_size = 16; 796: 797: /* Calculate page size so that the number of pages 798: * fits in 16 bits. This is because object modules 799: * are indexed by page number, stored as an unsigned short. 800: */ 801: while (1) 802: { 803: Lagain: 804: #if LOG 805: printf("g_page_size = %d\n", g_page_size); 806: #endif 807: unsigned offset = g_page_size; 808: 809: for (int i = 0; i < objmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
810: { ObjModule *om = objmodules.tdata()[i]; 811: 812: unsigned page = offset / g_page_size; 813: if (page > 0xFFFF) 814: { // Page size is too small, double it and try again 815: g_page_size *= 2; 816: goto Lagain; 817: } 818: 819: // Write out the object module m 820: if (om->flags & MFgentheadr) // if generate THEADR record 821: { 822: size_t size = strlen(om->name); 823: assert(size <= LIBIDMAX); 824: 825: offset += size + 5; 826: //offset += om->length - (size + 5); 827: offset += om->length; 828: } 829: else 830: offset += om->length; 831: 832: // Round the size of the file up to the next page size 833: // by filling with 0s 834: unsigned n = (g_page_size - 1) & offset; 835: if (n) 836: offset += g_page_size - n; 837: } 838: break; 839: } 840: 841: 842: /* Leave one page of 0s at start as a dummy library header. 843: * Fill it in later with the real data. 844: */ 845: libbuf->fill0(g_page_size); 846: 847: /* Write each object module into the library 848: */ 849: for (int i = 0; i < objmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
850: { ObjModule *om = objmodules.tdata()[i]; 851: 852: unsigned page = libbuf->offset / g_page_size; 853: assert(page <= 0xFFFF); 854: om->page = page; 855: 856: // Write out the object module om 857: if (om->flags & MFgentheadr) // if generate THEADR record 858: { 859: unsigned size = strlen(om->name); 860: unsigned char header[4 + LIBIDMAX + 1]; 861: 862: header [0] = THEADR; 863: header [1] = 2 + size; 864: header [2] = 0; 865: header [3] = size; 866: assert(size <= 0xFF - 2); 867: 868: memcpy(4 + header, om->name, size); 869: 870: // Compute and store record checksum 871: unsigned n = size + 4; 872: unsigned char checksum = 0; 873: unsigned char *p = header; 874: while (n--) 875: { checksum -= *p; 876: p++; 877: } 878: *p = checksum; 879: 880: libbuf->write(header, size + 5); 881: //libbuf->write(om->base, om->length - (size + 5)); 882: libbuf->write(om->base, om->length); 883: } 884: else 885: libbuf->write(om->base, om->length); 886: 887: // Round the size of the file up to the next page size 888: // by filling with 0s 889: unsigned n = (g_page_size - 1) & libbuf->offset; 890: if (n) 891: libbuf->fill0(g_page_size - n); 892: } 893: 894: // File offset of start of dictionary 895: unsigned offset = libbuf->offset; 896: 897: // Write dictionary header, then round it to a BUCKETPAGE boundary 898: unsigned short size = (BUCKETPAGE - ((short)offset + 3)) & (BUCKETPAGE - 1); 899: libbuf->writeByte(0xF1); 900: libbuf->writeword(size); 901: libbuf->fill0(size); 902: 903: // Create dictionary 904: unsigned char *bucketsP = NULL; 905: unsigned short ndicpages; 906: unsigned short padding = 32; 907: for (;;) 908: { 909: ndicpages = numDictPages(padding); 910: 911: #if LOG 912: printf("ndicpages = %d\n", ndicpages); 913: #endif 914: // Allocate dictionary 915: if (bucketsP) 916: bucketsP = (unsigned char *)realloc(bucketsP, ndicpages * BUCKETPAGE);
warning C6308: 'realloc' might return null pointer: assigning null pointer to 'bucketsP', which is passed as an argument to 'realloc', will cause the original memory block to be leaked
917: else 918: bucketsP = (unsigned char *)malloc(ndicpages * BUCKETPAGE); 919: assert(bucketsP); 920: memset(bucketsP, 0, ndicpages * BUCKETPAGE); 921: for (unsigned u = 0; u < ndicpages; u++) 922: { 923: // 'next available' slot 924: bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; 925: } 926: 927: if (FillDict(bucketsP, ndicpages)) 928: break; 929: padding += 16; // try again with more margins 930: } 931: 932: // Write dictionary 933: libbuf->write(bucketsP, ndicpages * BUCKETPAGE); 934: if (bucketsP) 935: free(bucketsP); 936: 937: // Create library header 938: #pragma pack(1) 939: struct Libheader 940: { 941: unsigned char recTyp; 942: unsigned short recLen; 943: long trailerPosn; 944: unsigned short ndicpages; 945: unsigned char flags; 946: char filler[ 6 ]; 947: }; 948: #pragma pack() 949: 950: Libheader libHeader; 951: memset(&libHeader, 0, sizeof(Libheader)); 952: libHeader.recTyp = 0xF0; 953: libHeader.recLen = 0x0D; 954: libHeader.trailerPosn = offset + (3 + size); 955: libHeader.recLen = g_page_size - 3; 956: libHeader.ndicpages = ndicpages; 957: libHeader.flags = 1; // always case sensitive 958: 959: // Write library header at start of buffer 960: memcpy(libbuf->data, &libHeader, sizeof(libHeader)); 961: } 962: