1: // Copyright (C) 1984-1998 by Symantec
   2: // Copyright (C) 2000-2011 by Digital Mars
   3: // All Rights Reserved
   4: // http://www.digitalmars.com
   5: // Written by Walter Bright
   6: /*
   7:  * This source file is made available for personal use
   8:  * only. The license is in /dmd/src/dmd/backendlicense.txt
   9:  * or /dm/src/dmd/backendlicense.txt
  10:  * For any other uses, please contact Digital Mars.
  11:  */
  12: 
  13: #if !HTOD && (SCPP || MARS)
  14: 
  15: #include        <stdio.h>
  16: #include        <string.h>
  17: #include        <stdlib.h>
  18: #include        <malloc.h>
  19: #include        <ctype.h>
  20: #include        <direct.h>
  21: 
  22: #include        "filespec.h"
  23: 
  24: #include        "cc.h"
  25: #include        "global.h"
  26: #include        "cgcv.h"
  27: #include        "code.h"
  28: #include        "type.h"
  29: #include        "outbuf.h"
  30: 
  31: #include        "md5.h"
  32: 
  33: #if MARS
  34: struct Loc
  35: {
  36:     char *filename;
  37:     unsigned linnum;
  38: 
  39:     Loc(int x)
  40:     {
  41:         linnum = x;
  42:         filename = NULL;
  43:     }
  44: };
  45: 
  46: void error(Loc loc, const char *format, ...);
  47: #endif
  48: 
  49: #if OMFOBJ
  50: 
  51: static char __file__[] = __FILE__;      // for tassert.h
  52: #include        "tassert.h"
  53: 
  54: #define MULTISCOPE      1       /* account for bug in MultiScope debugger
  55:                                    where it cannot handle a line number
  56:                                    with multiple offsets. We use a bit vector
  57:                                    to filter out the extra offsets.
  58:                                  */
  59: 
  60: #define TOOFFSET(a,b)   (I32 ? TOLONG(a,b) : TOWORD(a,b))
  61: 
  62: /**************************
  63:  * Record types:
  64:  */
  65: 
  66: #define RHEADR  0x6E
  67: #define REGINT  0x70
  68: #define REDATA  0x72
  69: #define RIDATA  0x74
  70: #define OVLDEF  0x76
  71: #define ENDREC  0x78
  72: #define BLKDEF  0x7A
  73: #define BLKEND  0x7C
  74: //#define DEBSYM        0x7E
  75: #define THEADR  0x80
  76: #define LHEADR  0x82
  77: #define PEDATA  0x84
  78: #define PIDATA  0x86
  79: #define COMENT  0x88
  80: #define MODEND  0x8A
  81: #define EXTDEF  0x8C
  82: #define TYPDEF  0x8E
  83: #define PUBDEF  0x90
  84: #define PUB386  0x91
  85: #define LOCSYM  0x92
  86: #define LINNUM  0x94
  87: #define LNAMES  0x96
  88: #define SEGDEF  0x98
  89: #define SEG386  0x99
  90: #define GRPDEF  0x9A
  91: #define FIXUPP  0x9C
  92: #define FIX386  0x9D
  93: #define LEDATA  0xA0
  94: #define LED386  0xA1
  95: #define LIDATA  0xA2
  96: #define LID386  0xA3
  97: #define LIBHED  0xA4
  98: #define LIBNAM  0xA6
  99: #define LIBLOC  0xA8
 100: #define LIBDIC  0xAA
 101: #define COMDEF  0xB0
 102: #define LEXTDEF 0xB4
 103: #define LPUBDEF 0xB6
 104: #define LCOMDEF 0xB8
 105: #define CEXTDEF 0xBC
 106: #define COMDAT  0xC2
 107: #define LINSYM  0xC4
 108: #define ALIAS   0xC6
 109: #define LLNAMES 0xCA
 110: 
 111: // Some definitions for .OBJ files. Trial and error to determine which
 112: // one to use when. Page #s refer to Intel spec on .OBJ files.
 113: 
 114: // Values for LOCAT byte: (pg. 71)
 115: #define LOCATselfrel    0x8000
 116: #define LOCATsegrel     0xC000
 117: // OR'd with one of the following:
 118: #define LOClobyte               0x0000
 119: #define LOCbase                 0x0800
 120: #define LOChibyte               0x1000
 121: #define LOCloader_resolved      0x1400
 122: 
 123: // Unfortunately, the fixup stuff is different for EASY OMF and Microsoft
 124: #define EASY_LOCoffset          0x1400          // 32 bit offset
 125: #define EASY_LOCpointer         0x1800          // 48 bit seg/offset
 126: 
 127: #define LOC32offset             0x2400
 128: #define LOC32tlsoffset          0x2800
 129: #define LOC32pointer            0x2C00
 130: 
 131: #define LOC16offset             0x0400
 132: #define LOC16pointer            0x0C00
 133: 
 134: #define LOCxx                   0x3C00
 135: 
 136: // FDxxxx are constants for the FIXDAT byte in fixup records (pg. 72)
 137: 
 138: #define FD_F0   0x00            // segment index
 139: #define FD_F1   0x10            // group index
 140: #define FD_F2   0x20            // external index
 141: #define FD_F4   0x40            // canonic frame of LSEG that contains Location
 142: #define FD_F5   0x50            // Target determines the frame
 143: 
 144: #define FD_T0   0               // segment index
 145: #define FD_T1   1               // group index
 146: #define FD_T2   2               // external index
 147: #define FD_T4   4               // segment index, 0 displacement
 148: #define FD_T5   5               // group index, 0 displacement
 149: #define FD_T6   6               // external index, 0 displacement
 150: 
 151: /***************
 152:  * Fixup list.
 153:  */
 154: 
 155: struct FIXUP
 156: {
 157:     struct FIXUP        *FUnext;
 158:     targ_size_t         FUoffset;       // offset from start of ledata
 159:     unsigned short      FUlcfd;         // LCxxxx | FDxxxx
 160:     unsigned short      FUframedatum;
 161:     unsigned short      FUtargetdatum;
 162: };
 163: 
 164: #define list_fixup(fl)  ((struct FIXUP *)list_ptr(fl))
 165: 
 166: #define seg_is_comdat(seg) ((seg) < 0)
 167: 
 168: /*****************************
 169:  * Ledata records
 170:  */
 171: 
 172: #define LEDATAMAX (1024-14)
 173: 
 174: struct Ledatarec
 175: {
 176:     char header[14];                    // big enough to handle COMDAT header
 177:     char data[LEDATAMAX];
 178:     int lseg;                           // segment value
 179:     unsigned i;                         // number of bytes in data
 180:     targ_size_t offset;                 // segment offset of start of data
 181:     struct FIXUP *fixuplist;            // fixups for this ledata
 182: 
 183:     // For COMDATs
 184:     unsigned char flags;                // flags byte of COMDAT
 185:     unsigned char alloctyp;             // allocation type of COMDAT
 186:     unsigned char align;                // align type
 187:     int typidx;
 188:     int pubbase;
 189:     int pubnamidx;
 190: };
 191: 
 192: #define list_ledata(dl) ((Ledatarec *)list_ptr(dl))
 193: 
 194: /*****************************
 195:  * For defining segments.
 196:  */
 197: 
 198: #define SEG_ATTR(A,C,B,P)       (((A) << 5) | ((C) << 2) | ((B) << 1) | (P))
 199: 
 200: // Segment alignment A
 201: #define SEG_ALIGN0      0       // absolute segment
 202: #define SEG_ALIGN1      1       // byte align
 203: #define SEG_ALIGN2      2       // word align
 204: #define SEG_ALIGN16     3       // paragraph align
 205: #define SEG_ALIGN4K     4       // 4Kb page align
 206: #define SEG_ALIGN4      5       // dword align
 207: 
 208: // Segment combine types C
 209: #define SEG_C_ABS       0
 210: #define SEG_C_PUBLIC    2
 211: #define SEG_C_STACK     5
 212: #define SEG_C_COMMON    6
 213: 
 214: // Segment type P
 215: #define USE16   0
 216: #define USE32   1
 217: 
 218: #define USE32_CODE      (4+2)           // use32 + execute/read
 219: #define USE32_DATA      (4+3)           // use32 + read/write
 220: 
 221: /**********************
 222:  * Struct to keep track of far segments and comdats.
 223:  */
 224: 
 225: #if 0
 226: typedef struct Farseg
 227: {
 228:     bool isfarseg;
 229:     int seg;                            // segment number
 230:     int lnameidx;                       // lname idx of segment name
 231:     int classidx;                       // lname idx of class name
 232:     unsigned attr;                      // segment attribute
 233:     targ_size_t origsize;               // original size
 234:     targ_size_t SDoffset;               // current size
 235:     long seek;                          // seek position in output file
 236: } Farseg;
 237: #endif
 238: 
 239: /*****************************
 240:  * Line number support.
 241:  */
 242: 
 243: #define LINNUMMAX       512
 244: 
 245: struct Linnum
 246: {
 247: #if MARS
 248:         const char *filename;   // source file name
 249: #else
 250:         Sfile *filptr;          // file pointer
 251: #endif
 252:         int cseg;               // our internal segment number
 253:         int seg;                // segment/public index
 254:         int i;                  // used in data[]
 255:         char data[LINNUMMAX];   // linnum/offset data
 256: };
 257: 
 258: #define LINRECMAX       (2 + 255 * 2)   // room for 255 line numbers
 259: 
 260: /************************************
 261:  * State of object file.
 262:  */
 263: 
 264: struct Objstate
 265: {
 266:     const char *modname;
 267:     char *csegname;
 268:     Outbuffer *buf;     // output buffer
 269: 
 270:     int fdsegattr;      // far data segment attribute
 271:     int csegattr;       // code segment attribute
 272: 
 273:     targ_size_t codeSegOffset;  // size of default code segment
 274: 
 275:     int farsegi;                // how many in farseg[]
 276:     int lastfarcodesegi;        // index of last far code seg
 277:     int lastfardatasegi;        // index of last far data seg
 278: 
 279:     int LOCoffset;
 280:     int LOCpointer;
 281: 
 282:     int mlidata;
 283:     int mpubdef;
 284:     int mfixupp;
 285:     int mmodend;
 286: 
 287:     int lnameidx;               // index of next LNAMES record
 288:     int segidx;                 // index of next SEGDEF record
 289:     int extidx;                 // index of next EXTDEF record
 290:     int pubnamidx;              // index of COMDAT public name index
 291: 
 292:     Symbol *startaddress;       // if !NULL, then Symbol is start address
 293: 
 294: #ifdef DEBUG
 295:     int fixup_count;
 296: #endif
 297: 
 298:     Ledatarec *ledata;
 299:     list_t ledata_list;         // list of Ledatarec blocks
 300: 
 301:     // Line numbers
 302:     list_t linnum_list;
 303:     char *linrec;               // line number record
 304:     unsigned linreci;           // index of next avail in linrec[]
 305:     unsigned linrecheader;      // size of line record header
 306:     unsigned linrecnum;         // number of line record entries
 307:     list_t linreclist;          // list of line records
 308:     int mlinnum;
 309:     int recseg;
 310:     int term;
 311: #if MULTISCOPE
 312:     vec_t linvec;               // bit vector of line numbers used
 313:     vec_t offvec;               // and offsets used
 314: #endif
 315: 
 316:     int fiseg;                  // segment number of FI segment
 317:     int fisegi;                 // index into farseg[] of FI segment
 318: 
 319: #if MARS
 320:     int fmseg;                  // segment number of FM segment
 321:     int fmsegi;                 // index into farseg[] of FM segment
 322: #endif
 323: 
 324:     int tlsseg;                 // TLS segment
 325:     int tlssegi;                // index into farseg[] of tls segment
 326:     int fardataidx;
 327: 
 328:     char pubdata[1024];
 329:     int pubdatai;
 330: 
 331:     char extdata[1024];
 332:     int extdatai;
 333: 
 334:     // For obj_far16thunk
 335:     int code16segi;
 336:     int code16;
 337:     targ_size_t CODE16offset;
 338: 
 339:     int fltused;
 340:     int nullext;
 341: };
 342: 
 343: seg_data **SegData;
 344: static int seg_count;
 345: static int seg_max;
 346: 
 347: targ_size_t     Coffset;        /* size of current code segment         */
 348: 
 349: static Objstate obj;
 350: 
 351: STATIC void obj_defaultlib();
 352: STATIC void objheader (char *csegname);
 353: STATIC char * objmodtoseg (const char *modname);
 354: STATIC void obj_browse_flush();
 355: STATIC int obj_newfarseg (targ_size_t size,int);
 356: STATIC void linnum_flush(void);
 357: STATIC void linnum_term(void);
 358: STATIC void objsegdef (int attr,targ_size_t size,int segnamidx,int classnamidx);
 359: STATIC void obj_modend();
 360: STATIC void objfixupp (struct FIXUP *);
 361: STATIC void outextdata();
 362: STATIC void outpubdata();
 363: STATIC void ledata_new (int seg,targ_size_t offset);
 364: 
 365: char *id_compress(char *id, int idlen);
 366: 
 367: /*******************************
 368:  * Output an object file data record.
 369:  * Input:
 370:  *      rectyp  =       record type
 371:  *      record  ->      the data
 372:  *      reclen  =       # of bytes in record
 373:  */
 374: 
 375: void objrecord(unsigned rectyp,const char *record,unsigned reclen)
 376: {   Outbuffer *o = obj.buf;
 377: 
 378:     //printf("rectyp = x%x, record[0] = x%x, reclen = x%x\n",rectyp,record[0],reclen);
 379:     o->reserve(reclen + 4);
 380:     o->writeByten(rectyp);
 381:     o->writeWordn(reclen + 1);  // record length includes checksum
 382:     o->writen(record,reclen);
 383:     o->writeByten(0);           // use 0 for checksum
 384: }
 385: 
 386: 
 387: /**************************
 388:  * Insert an index number.
 389:  * Input:
 390:  *      p -> where to put the 1 or 2 byte index
 391:  *      index = the 15 bit index
 392:  * Returns:
 393:  *      # of bytes stored
 394:  */
 395: 
 396: extern void error(const char *filename, unsigned linnum, const char *format, ...);
 397: extern void fatal();
 398: 
 399: void too_many_symbols()
 400: {
 401: #if SCPP
 402:     err_fatal(EM_too_many_symbols, 0x7FFF);
 403: #else // MARS
 404:     error(NULL, 0, "more than %d symbols in object file", 0x7FFF);
 405:     fatal();
 406: #endif
 407: }
 408: 
 409: #if !DEBUG && TX86 && __INTSIZE == 4 && !defined(_MSC_VER)
 410: __declspec(naked) int __pascal insidx(char *p,unsigned index)
 411: {
 412: #undef AL
 413: #undef AH
 414: #undef DL
 415: #undef DH
 416:     _asm
 417:     {
 418:         mov     EAX,index - 4[ESP]
 419:         mov     ECX,p - 4[ESP]
 420:         cmp     EAX,0x7F
 421:         jae     L1
 422:         mov     [ECX],AL
 423:         mov     EAX,1
 424:         ret     8
 425: 
 426: 
 427:     L1:
 428:         cmp     EAX,0x7FFF
 429:         ja      L2
 430: 
 431:         mov     1[ECX],AL
 432:         or      EAX,0x8000
 433:         mov     [ECX],AH
 434:         mov     EAX,2
 435:         ret     8
 436:     }
 437:     L2:
 438:         too_many_symbols();
 439: }
 440: #else
 441: __inline int insidx(char *p,unsigned index)
 442: {
 443:     //if (index > 0x7FFF) printf("index = x%x\n",index);
 444:     /* OFM spec says it could be <=0x7F, but that seems to cause
 445:      * "library is corrupted" messages. Unverified. See Bugzilla 3601
 446:      */
 447:     if (index < 0x7F)
 448:     {   *p = index;
 449:         return 1;
 450:     }
 451:     else if (index <= 0x7FFF)
 452:     {
 453:         *(p + 1) = index;
 454:         *p = (index >> 8) | 0x80;
 455:         return 2;
 456:     }
 457:     else
 458:     {   too_many_symbols();
 459:         return 0;
 460:     }
 461: }
 462: #endif
 463: 
 464: /**************************
 465:  * Insert a type index number.
 466:  * Input:
 467:  *      p -> where to put the 1 or 2 byte index
 468:  *      index = the 15 bit index
 469:  * Returns:
 470:  *      # of bytes stored
 471:  */
 472: 
 473: __inline int instypidx(char *p,unsigned index)
 474: {
 475:     if (index <= 127)
 476:     {   *p = index;
 477:         return 1;
 478:     }
 479:     else if (index <= 0x7FFF)
 480:     {   *(p + 1) = index;
 481:         *p = (index >> 8) | 0x80;
 482:         return 2;
 483:     }
 484:     else                        // overflow
 485:     {   *p = 0;                 // the linker ignores this field anyway
 486:         return 1;
 487:     }
 488: }
 489: 
 490: /****************************
 491:  * Read index.
 492:  */
 493: 
 494: #define getindex(p) ((*(p) & 0x80) \
 495:     ? ((*(unsigned char *)(p) & 0x7F) << 8) | *((unsigned char *)(p) + 1) \
 496:     : *(unsigned char *)(p))
 497: 
 498: /*****************************
 499:  * Returns:
 500:  *      # of bytes stored
 501:  */
 502: 
 503: #define ONS_OHD 4               // max # of extra bytes added by obj_namestring()
 504: 
 505: STATIC int obj_namestring(char *p,const char *name)
 506: {   unsigned len;
 507: 
 508:     len = strlen(name);
 509:     if (len > 255)
 510:     {   p[0] = 0xFF;
warning C4309: '=' : truncation of constant value
511: p[1] = 0; 512: #ifdef DEBUG 513: assert(len <= 0xFFFF); 514: #endif 515: TOWORD(p + 2,len); 516: memcpy(p + 4,name,len); 517: len += ONS_OHD; 518: } 519: else 520: { p[0] = len; 521: memcpy(p + 1,name,len); 522: len++; 523: } 524: return len; 525: } 526: 527: /****************************** 528: * Allocate a new segment. 529: * Return index for the new segment. 530: */ 531: 532: seg_data *getsegment() 533: { 534: int seg = ++seg_count; 535: if (seg_count == seg_max) 536: { 537: seg_max += 10; 538: SegData = (seg_data **)mem_realloc(SegData, seg_max * sizeof(seg_data)); 539: memset(&SegData[seg_count], 0, 10 * sizeof(seg_data *)); 540: } 541: assert(seg_count < seg_max); 542: if (SegData[seg]) 543: memset(SegData[seg], 0, sizeof(seg_data)); 544: else 545: SegData[seg] = (seg_data *)mem_calloc(sizeof(seg_data)); 546: 547: seg_data *pseg = SegData[seg]; 548: pseg->SDseg = seg; 549: return pseg; 550: } 551: 552: 553: /****************************** 554: * Perform initialization that applies to all .obj output files. 555: * Input: 556: * filename source file name 557: * csegname code segment name (can be NULL) 558: */ 559: 560: void obj_init(Outbuffer *objbuf, const char *filename, const char *csegname) 561: { 562: memset(&obj,0,sizeof(obj)); 563: 564: obj.buf = objbuf; 565: obj.buf->reserve(40000); 566: 567: obj.tlsseg = UNKNOWN; 568: 569: obj.lastfarcodesegi = -1; 570: obj.lastfardatasegi = -1; 571: 572: obj.mlidata = LIDATA; 573: obj.mpubdef = PUBDEF; 574: obj.mfixupp = FIXUPP; 575: obj.mmodend = MODEND; 576: obj.mlinnum = LINNUM; 577: 578: 579: // Reset for different OBJ file formats 580: if (I32) 581: { if (config.flags & CFGeasyomf) 582: { obj.LOCoffset = EASY_LOCoffset; 583: obj.LOCpointer = EASY_LOCpointer; 584: } 585: else 586: { 587: obj.mlidata = LID386; 588: obj.mpubdef = PUB386; 589: obj.mfixupp = FIX386; 590: obj.mmodend = MODEND + 1; 591: obj.LOCoffset = LOC32offset; 592: obj.LOCpointer = LOC32pointer; 593: } 594: obj.fdsegattr = SEG_ATTR(SEG_ALIGN16,SEG_C_PUBLIC,0,USE32); 595: obj.csegattr = SEG_ATTR(SEG_ALIGN4, SEG_C_PUBLIC,0,USE32); 596: } 597: else 598: { 599: obj.LOCoffset = LOC16offset; 600: obj.LOCpointer = LOC16pointer; 601: obj.fdsegattr = SEG_ATTR(SEG_ALIGN16,SEG_C_PUBLIC,0,USE16); 602: obj.csegattr = SEG_ATTR(SEG_ALIGN2, SEG_C_PUBLIC,0,USE16); 603: } 604: 605: if (config.flags4 & CFG4speed && // if optimized for speed 606: config.target_cpu == TARGET_80486) 607: // 486 is only CPU that really benefits from alignment 608: obj.csegattr = I32 ? SEG_ATTR(SEG_ALIGN16, SEG_C_PUBLIC,0,USE32) 609: : SEG_ATTR(SEG_ALIGN16, SEG_C_PUBLIC,0,USE16); 610: 611: if (!SegData) 612: { seg_max = UDATA + 10; 613: SegData = (seg_data **)mem_calloc(seg_max * sizeof(seg_data *)); 614: } 615: 616: for (int i = 0; i < seg_max; i++) 617: { 618: if (SegData[i]) 619: memset(SegData[i], 0, sizeof(seg_data)); 620: else 621: SegData[i] = (seg_data *)mem_calloc(sizeof(seg_data)); 622: } 623: 624: SegData[CODE]->SDseg = CODE; 625: SegData[DATA]->SDseg = DATA; 626: SegData[CDATA]->SDseg = CDATA; 627: SegData[UDATA]->SDseg = UDATA; 628: seg_count = UDATA; 629: 630: if (config.fulltypes) 631: { 632: SegData[DEBSYM]->SDseg = DEBSYM; 633: SegData[DEBTYP]->SDseg = DEBTYP; 634: seg_count = DEBTYP; 635: } 636: 637: obj_theadr(filename); 638: obj.modname = filename; 639: if (!csegname || !*csegname) // if no code seg name supplied 640: obj.csegname = objmodtoseg(obj.modname); // generate one 641: else 642: obj.csegname = mem_strdup(csegname); // our own copy 643: objheader(obj.csegname); 644: objseggrp(0,0,0,0); // obj seg and grp info 645: ledata_new(cseg,0); // so ledata is never NULL 646: if (config.fulltypes) // if full typing information 647: cv_init(); // initialize debug output code 648: } 649: 650: /************************** 651: * Initialize the start of object output for this particular .obj file. 652: */ 653: 654: void obj_initfile(const char *filename,const char *csegname, const char *modname) 655: { 656: } 657: 658: /*************************** 659: * Fixup and terminate object file. 660: */ 661: 662: void obj_termfile() 663: { 664: } 665: 666: /********************************* 667: * Terminate package. 668: */ 669: 670: void obj_term() 671: { 672: //printf("obj_term()\n"); 673: int i; 674: list_t dl; 675: unsigned long size; 676: 677: #if SCPP 678: if (!errcnt) 679: #endif 680: { obj_defaultlib(); 681: outfixlist(); // backpatches 682: } 683: 684: if (config.fulltypes) 685: cv_term(); // write out final debug info 686: outextdata(); // finish writing EXTDEFs 687: outpubdata(); // finish writing PUBDEFs 688: 689: // Put out LEDATA records and associated fixups 690: obj.ledata_list = list_reverse(obj.ledata_list); 691: for (dl = obj.ledata_list; dl; dl = list_next(dl)) 692: { Ledatarec *d = list_ledata(dl); 693: 694: if (d->i) // if any data in this record 695: { // Fill in header 696: int headersize; 697: int rectyp; 698: int lseg = d->lseg; 699: char header[sizeof(d->header)]; 700: 701: if (lseg < 0) // if COMDAT 702: { 703: header[0] = d->flags | (d->offset ? 1 : 0); // continuation flag 704: header[1] = d->alloctyp; 705: header[2] = d->align; 706: TOOFFSET(header + 3,d->offset); 707: headersize = 3 + intsize; 708: headersize += instypidx(header + headersize,d->typidx); 709: if ((header[1] & 0x0F) == 0) 710: { // Group index 711: header[headersize] = (d->pubbase == DATA) ? 1 : 0; 712: headersize++; 713: 714: // Segment index 715: headersize += insidx(header + headersize,d->pubbase); 716: } 717: headersize += insidx(header + headersize,d->pubnamidx); 718: 719: rectyp = I32 ? COMDAT + 1 : COMDAT; 720: } 721: else 722: { 723: rectyp = LEDATA; 724: headersize = insidx(header,lseg); 725: if (intsize == LONGSIZE || d->offset & ~0xFFFFL) 726: { if (!(config.flags & CFGeasyomf)) 727: rectyp++; 728: TOLONG(header + headersize,d->offset); 729: headersize += 4; 730: } 731: else 732: { 733: TOWORD(header + headersize,d->offset); 734: headersize += 2; 735: } 736: } 737: assert(headersize <= sizeof(d->header)); 738: 739: // Right-justify data in d->header[] 740: memcpy(d->header + sizeof(d->header) - headersize,header,headersize); 741: //printf("objrecord(rectyp=x%02x, d=%p, p=%p, size = %d)\n", 742: //rectyp,d,d->header + (sizeof(d->header) - headersize),d->i + headersize); 743: 744: objrecord(rectyp,d->header + (sizeof(d->header) - headersize), 745: d->i + headersize); 746: objfixupp(d->fixuplist); 747: } 748: } 749: #if TERMCODE 750: list_free(&obj.ledata_list,mem_freefp); 751: #endif 752: 753: linnum_term(); 754: obj_modend(); 755: 756: size = obj.buf->size(); 757: obj.buf->setsize(0); // rewind file 758: obj_theadr(obj.modname); 759: objheader(obj.csegname); 760: mem_free(obj.csegname); 761: if (obj.lastfarcodesegi != -1) 762: { 763: SegData[obj.lastfarcodesegi]->SDoffset = Coffset; 764: Coffset = obj.codeSegOffset; // reset for benefit of next line 765: } 766: objseggrp(Coffset,Doffset,0,UDoffset); // do real sizes 767: 768: // Update any out-of-date far segment sizes 769: for (i = 0; i <= seg_count; i++) 770: { seg_data *f = SegData[i]; 771: if (f->isfarseg && f->origsize != f->SDoffset) 772: { obj.buf->setsize(f->seek); 773: objsegdef(f->attr,f->SDoffset,f->lnameidx,f->classidx); 774: } 775: } 776: //mem_free(obj.farseg); 777: 778: #if 0 779: printf("Max # of fixups = %d\n",obj.fixup_count); 780: #endif 781: 782: obj.buf->setsize(size); 783: } 784: 785: /***************************** 786: * Line number support. 787: */ 788: 789: /*************************** 790: * Record line number linnum at offset. 791: * Input: 792: * cseg current code segment (negative for COMDAT segments) 793: * pubnamidx 794: * obj.mlinnum LINNUM or LINSYM 795: */ 796: 797: void objlinnum(Srcpos srcpos,targ_size_t offset) 798: { 799: unsigned linnum = srcpos.Slinnum; 800: 801: #if 0 802: #if MARS || SCPP 803: printf("objlinnum(cseg=%d, offset=0x%lx) ", cseg, offset); 804: #endif 805: srcpos.print(""); 806: #endif 807: 808: char linos2 = config.exe == EX_OS2 && cseg >= 0; 809: 810: #if MARS 811: if (!obj.term && 812: (cseg < 0 || (srcpos.Sfilename && srcpos.Sfilename != obj.modname))) 813: #else 814: if (!srcpos.Sfilptr) 815: return; 816: sfile_debug(&srcpos_sfile(srcpos)); 817: if (!obj.term && (!(srcpos_sfile(srcpos).SFflags & SFtop) || (cseg < 0 && !obj.term))) 818: #endif 819: { // Not original source file, or a COMDAT. 820: // Save data away and deal with it at close of compile. 821: // It is done this way because presumably 99% of the lines 822: // will be in the original source file, so we wish to minimize 823: // memory consumption and maximize speed. 824: list_t ll; 825: struct Linnum *ln; 826: 827: if (linos2) 828: return; // BUG: not supported under OS/2 829: for (ll = obj.linnum_list; 1; ll = list_next(ll)) 830: { 831: if (!ll) 832: { 833: ln = (struct Linnum *) mem_calloc(sizeof(struct Linnum)); 834: #if MARS 835: ln->filename = srcpos.Sfilename; 836: #else 837: ln->filptr = *srcpos.Sfilptr; 838: #endif 839: ln->cseg = cseg; 840: ln->seg = obj.pubnamidx; 841: list_prepend(&obj.linnum_list,ln); 842: break; 843: } 844: ln = (Linnum *)list_ptr(ll); 845: if ( 846: #if MARS 847: (ln->filename == srcpos.Sfilename) && 848: #endif 849: #if SCPP 850: (ln->filptr == *srcpos.Sfilptr) && 851: #endif 852: ln->cseg == cseg && 853: ln->i < LINNUMMAX - 6) 854: break; 855: } 856: TOWORD(&ln->data[ln->i],linnum); 857: TOOFFSET(&ln->data[ln->i + 2],offset); 858: ln->i += 2 + intsize; 859: } 860: else 861: { 862: if (linos2 && obj.linreci > LINRECMAX - 8) 863: obj.linrec = NULL; // allocate a new one 864: else if (cseg != obj.recseg) 865: linnum_flush(); 866: 867: if (!obj.linrec) // if not allocated 868: { obj.linrec = (char *) mem_calloc(LINRECMAX); 869: obj.linrec[0] = 0; // base group / flags 870: obj.linrecheader = 1 + insidx(obj.linrec + 1,cseg < 0 ? obj.pubnamidx : cseg); 871: obj.linreci = obj.linrecheader; 872: obj.recseg = cseg; 873: #if MULTISCOPE 874: if (!obj.linvec) 875: { obj.linvec = vec_calloc(1000); 876: obj.offvec = vec_calloc(1000); 877: } 878: #endif 879: if (linos2) 880: { 881: if (!obj.linreclist) // if first line number record 882: obj.linreci += 8; // leave room for header 883: list_append(&obj.linreclist,obj.linrec); 884: } 885: 886: // Select record type to use 887: obj.mlinnum = (cseg < 0) ? LINSYM : LINNUM; 888: if (I32 && !(config.flags & CFGeasyomf)) 889: obj.mlinnum++; 890: } 891: else if (obj.linreci > LINRECMAX - (2 + intsize))
warning C4018: '>' : signed/unsigned mismatch
892: { objrecord(obj.mlinnum,obj.linrec,obj.linreci); // output data 893: obj.linreci = obj.linrecheader; 894: if (cseg < 0) // if LINSYM record 895: obj.linrec[0] |= 1; // continuation bit 896: } 897: #if MULTISCOPE 898: if (linnum >= vec_numbits(obj.linvec)) 899: obj.linvec = vec_realloc(obj.linvec,linnum + 1000); 900: if (offset >= vec_numbits(obj.offvec)) 901: { 902: #if __INTSIZE == 2 903: unsigned newsize = (unsigned)offset * 2; 904: 905: if (offset >= 0x8000) 906: { newsize = 0xFF00; 907: assert(offset < newsize); 908: } 909: if (newsize != vec_numbits(obj.offvec)) 910: obj.offvec = vec_realloc(obj.offvec,newsize); 911: #else 912: if (offset < 0xFF00) // otherwise we overflow ph_malloc() 913: obj.offvec = vec_realloc(obj.offvec,offset * 2); 914: #endif 915: } 916: if ( 917: #if 1 // disallow multiple offsets per line 918: !vec_testbit(linnum,obj.linvec) && // if linnum not already used 919: #endif 920: // disallow multiple lines per offset 921: (offset >= 0xFF00 || !vec_testbit(offset,obj.offvec))) // and offset not already used 922: #endif 923: { 924: #if MULTISCOPE 925: vec_setbit(linnum,obj.linvec); // mark linnum as used 926: if (offset < 0xFF00) 927: vec_setbit(offset,obj.offvec); // mark offset as used 928: #endif 929: TOWORD(obj.linrec + obj.linreci,linnum); 930: if (linos2) 931: { obj.linrec[obj.linreci + 2] = 1; // source file index 932: TOLONG(obj.linrec + obj.linreci + 4,offset); 933: obj.linrecnum++; 934: obj.linreci += 8; 935: } 936: else 937: { 938: TOOFFSET(obj.linrec + obj.linreci + 2,offset); 939: obj.linreci += 2 + intsize; 940: } 941: } 942: } 943: } 944: 945: /*************************** 946: * Flush any pending line number records. 947: */ 948: 949: STATIC void linnum_flush() 950: { 951: if (obj.linreclist) 952: { list_t list; 953: size_t len; 954: 955: obj.linrec = (char *) list_ptr(obj.linreclist); 956: TOWORD(obj.linrec + 6,obj.linrecnum); 957: list = obj.linreclist; 958: while (1) 959: { obj.linrec = (char *) list_ptr(list); 960: 961: list = list_next(list); 962: if (list) 963: { objrecord(obj.mlinnum,obj.linrec,LINRECMAX); 964: mem_free(obj.linrec); 965: } 966: else 967: { objrecord(obj.mlinnum,obj.linrec,obj.linreci); 968: break; 969: } 970: } 971: list_free(&obj.linreclist,FPNULL); 972: 973: // Put out File Names Table 974: TOLONG(obj.linrec + 2,0); // record no. of start of source (???) 975: TOLONG(obj.linrec + 6,obj.linrecnum); // number of primary source records 976: TOLONG(obj.linrec + 10,1); // number of source and listing files 977: len = obj_namestring(obj.linrec + 14,obj.modname); 978: assert(14 + len <= LINRECMAX); 979: objrecord(obj.mlinnum,obj.linrec,14 + len); 980: 981: mem_free(obj.linrec); 982: obj.linrec = NULL; 983: } 984: else if (obj.linrec) // if some line numbers to send 985: { objrecord(obj.mlinnum,obj.linrec,obj.linreci); 986: mem_free(obj.linrec); 987: obj.linrec = NULL; 988: } 989: #if MULTISCOPE 990: vec_clear(obj.linvec); 991: vec_clear(obj.offvec); 992: #endif 993: } 994: 995: /************************************* 996: * Terminate line numbers. 997: */ 998: 999: STATIC void linnum_term() 1000: { list_t ll; 1001: #if SCPP 1002: Sfile *lastfilptr = NULL; 1003: #endif 1004: #if MARS 1005: const char *lastfilename = NULL; 1006: #endif 1007: int csegsave = cseg; 1008: 1009: linnum_flush(); 1010: obj.term = 1; 1011: while (obj.linnum_list) 1012: { struct Linnum *ln; 1013: unsigned u; 1014: Srcpos srcpos; 1015: targ_size_t offset; 1016: 1017: ll = obj.linnum_list; 1018: ln = (struct Linnum *) list_ptr(ll); 1019: #if SCPP 1020: Sfile *filptr = ln->filptr; 1021: if (filptr != lastfilptr) 1022: { obj_theadr(filptr->SFname); 1023: lastfilptr = filptr; 1024: } 1025: #endif 1026: #if MARS 1027: const char *filename = ln->filename; 1028: if (filename != lastfilename) 1029: { 1030: if (filename) 1031: obj_theadr(filename); 1032: lastfilename = filename; 1033: } 1034: #endif 1035: while (1) 1036: { 1037: cseg = ln->cseg; 1038: obj.pubnamidx = ln->seg; 1039: #if MARS 1040: srcpos.Sfilename = ln->filename; 1041: #else 1042: srcpos.Sfilptr = &ln->filptr; 1043: #endif 1044: for (u = 0; u < ln->i; )
warning C4018: '<' : signed/unsigned mismatch
1045: { 1046: srcpos.Slinnum = *(unsigned short *)&ln->data[u]; 1047: u += 2; 1048: if (I32) 1049: offset = *(unsigned long *)&ln->data[u]; 1050: else 1051: offset = *(unsigned short *)&ln->data[u]; 1052: objlinnum(srcpos,offset); 1053: u += intsize; 1054: } 1055: linnum_flush(); 1056: ll = list_next(ll); 1057: list_subtract(&obj.linnum_list,ln); 1058: mem_free(ln); 1059: L1: 1060: if (!ll) 1061: break; 1062: ln = (struct Linnum *) list_ptr(ll); 1063: #if SCPP 1064: if (filptr != ln->filptr) 1065: #else 1066: if (filename != ln->filename) 1067: #endif 1068: { ll = list_next(ll); 1069: goto L1; 1070: } 1071: } 1072: } 1073: cseg = csegsave; 1074: #if MULTISCOPE 1075: vec_free(obj.linvec); 1076: vec_free(obj.offvec); 1077: #endif 1078: } 1079: 1080: /******************************* 1081: * Set start address 1082: */ 1083: 1084: void obj_startaddress(Symbol *s) 1085: { 1086: obj.startaddress = s; 1087: } 1088: 1089: /******************************* 1090: * Output DOSSEG coment record. 1091: */ 1092: 1093: void obj_dosseg() 1094: { static const char dosseg[] = { 0x80,0x9E };
warning C4309: 'initializing' : truncation of constant value
warning C4309: 'initializing' : truncation of constant value
1095: 1096: objrecord(COMENT,dosseg,sizeof(dosseg)); 1097: } 1098: 1099: /******************************* 1100: * Embed comment record. 1101: */ 1102: 1103: STATIC void obj_comment(unsigned char x, const char *string, size_t len) 1104: { 1105: char __ss *library; 1106: 1107: library = (char __ss *) alloca(2 + len);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1108: library[0] = 0; 1109: library[1] = x; 1110: memcpy(library + 2,string,len); 1111: objrecord(COMENT,library,len + 2); 1112: } 1113: 1114: /******************************* 1115: * Output library name. 1116: * Output: 1117: * name is modified 1118: */ 1119: 1120: void obj_includelib(const char *name) 1121: { const char *p; 1122: size_t len = strlen(name); 1123: 1124: p = filespecdotext(name); 1125: if (!filespeccmp(p,".lib"))
warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
1126: len -= strlen(p); // lop off .LIB extension 1127: obj_comment(0x9F, name, len); 1128: } 1129: 1130: /************************** 1131: * Embed string in executable. 1132: */ 1133: 1134: void obj_exestr(const char *p) 1135: { 1136: obj_comment(0xA4,p, strlen(p)); 1137: } 1138: 1139: /************************** 1140: * Embed string in obj. 1141: */ 1142: 1143: void obj_user(const char *p) 1144: { 1145: obj_comment(0xDF,p, strlen(p)); 1146: } 1147: 1148: /********************************* 1149: * Put out default library name. 1150: */ 1151: 1152: STATIC void obj_defaultlib() 1153: { 1154: char library[4]; // default library 1155: static const char model[MEMMODELS] = {'S','M','C','L','V'}; 1156: 1157: #if MARS 1158: memcpy(library,"SM?",4); 1159: #else 1160: memcpy(library,"SD?",4); 1161: #endif 1162: switch (config.exe) 1163: { 1164: case EX_OS2: 1165: library[2] = 'F'; 1166: case EX_OS1: 1167: library[1] = 'O'; 1168: break; 1169: case EX_NT: 1170: #if MARS 1171: library[1] = 'M'; 1172: #else 1173: library[1] = 'N'; 1174: #endif 1175: library[2] = (config.flags4 & CFG4dllrtl) ? 'D' : 'N'; 1176: break; 1177: case EX_DOSX: 1178: case EX_PHARLAP: 1179: library[2] = 'X'; 1180: break; 1181: default: 1182: library[2] = model[config.memmodel]; 1183: if (config.wflags & WFwindows) 1184: library[1] = 'W'; 1185: break; 1186: } 1187: 1188: if (!(config.flags2 & CFG2nodeflib)) 1189: { 1190: obj_includelib(configv.deflibname ? configv.deflibname : library); 1191: } 1192: } 1193: 1194: /******************************* 1195: * Output a weak extern record. 1196: * s1 is the weak extern, s2 is its default resolution. 1197: */ 1198: 1199: void obj_wkext(Symbol *s1,Symbol *s2) 1200: { char buffer[2+2+2]; 1201: int i; 1202: int x2; 1203: 1204: printf("obj_wkext(%s)\n", s1->Sident); 1205: if (s2) 1206: x2 = s2->Sxtrnnum; 1207: else 1208: { 1209: if (!obj.nullext) 1210: { 1211: obj.nullext = objextdef("__nullext"); 1212: } 1213: x2 = obj.nullext; 1214: } 1215: outextdata(); 1216: buffer[0] = 0x80;
warning C4309: '=' : truncation of constant value
1217: buffer[1] = 0xA8;
warning C4309: '=' : truncation of constant value
1218: i = 2; 1219: i += insidx(&buffer[2],s1->Sxtrnnum); 1220: i += insidx(&buffer[i],x2); 1221: objrecord(COMENT,buffer,i); 1222: } 1223: 1224: /******************************* 1225: * Output a lazy extern record. 1226: * s1 is the lazy extern, s2 is its default resolution. 1227: */ 1228: 1229: void obj_lzext(Symbol *s1,Symbol *s2) 1230: { char buffer[2+2+2]; 1231: int i; 1232: 1233: outextdata(); 1234: buffer[0] = 0x80;
warning C4309: '=' : truncation of constant value
1235: buffer[1] = 0xA9;
warning C4309: '=' : truncation of constant value
1236: i = 2; 1237: i += insidx(&buffer[2],s1->Sxtrnnum); 1238: i += insidx(&buffer[i],s2->Sxtrnnum); 1239: objrecord(COMENT,buffer,i); 1240: } 1241: 1242: /******************************* 1243: * Output an alias definition record. 1244: */ 1245: 1246: void obj_alias(const char *n1,const char *n2) 1247: { unsigned len; 1248: char *buffer; 1249: 1250: buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1251: len = obj_namestring(buffer,n1); 1252: len += obj_namestring(buffer + len,n2); 1253: objrecord(ALIAS,buffer,len); 1254: } 1255: 1256: /******************************* 1257: * Output module name record. 1258: */ 1259: 1260: void obj_theadr(const char *modname) 1261: { 1262: //printf("obj_theadr(%s)\n", modname); 1263: 1264: // Convert to absolute file name, so debugger can find it anywhere 1265: char absname[260]; 1266: if (config.fulltypes && 1267: modname[0] != '\\' && modname[0] != '/' && !(modname[0] && modname[1] == ':')) 1268: { 1269: if (getcwd(absname, sizeof(absname)))
warning C4996: 'getcwd': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _getcwd. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\direct.h(117) : see declaration of 'getcwd'
1270: { 1271: int len = strlen(absname); 1272: if(absname[len - 1] != '\\' && absname[len - 1] != '/') 1273: absname[len++] = '\\'; 1274: strcpy(absname + len, modname);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
1275: modname = absname; 1276: } 1277: } 1278: 1279: char *theadr = (char *)alloca(ONS_OHD + strlen(modname));
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1280: int i = obj_namestring(theadr,modname); 1281: objrecord(THEADR,theadr,i); // module name record 1282: } 1283: 1284: /******************************* 1285: * Embed compiler version in .obj file. 1286: */ 1287: 1288: void obj_compiler() 1289: { 1290: static const char compiler[] = "\0\xDB""Digital Mars C/C++" 1291: VERSION 1292: ; // compiled by ... 1293: 1294: objrecord(COMENT,compiler,sizeof(compiler) - 1); 1295: } 1296: 1297: /******************************* 1298: * Output header stuff for object files. 1299: * Input: 1300: * csegname Name to use for code segment (NULL if use default) 1301: */ 1302: 1303: STATIC void objheader(char *csegname) 1304: { 1305: char *nam;
warning C4101: 'nam' : unreferenced local variable
1306: static char lnames[] = 1307: "\0\06DGROUP\05_TEXT\04CODE\05_DATA\04DATA\05CONST\04_BSS\03BSS\ 1308: \07$$TYPES\06DEBTYP\011$$SYMBOLS\06DEBSYM"; 1309: 1310: #define DATACLASS 6 // data class lname index 1311: #define BSSCLASS 9 // BSS class lname index 1312: 1313: // Include debug segment names if inserting type information 1314: int lnamesize = config.fulltypes ? sizeof(lnames) - 1 : sizeof(lnames) - 1 - 32; 1315: int texti = 8; // index of _TEXT 1316: 1317: static char comment[] = {0,0x9D,'0','?','O'}; // memory model
warning C4309: 'initializing' : truncation of constant value
1318: static char model[MEMMODELS] = {'s','m','c','l','v'}; 1319: static char exten[] = {0,0xA1,1,'C','V'}; // extended format
warning C4309: 'initializing' : truncation of constant value
1320: static char pmdeb[] = {0x80,0xA1,1,'H','L','L',0}; // IBM PM debug format
warning C4309: 'initializing' : truncation of constant value
warning C4309: 'initializing' : truncation of constant value
1321: 1322: if (I32) 1323: { if (config.flags & CFGeasyomf) 1324: { 1325: // Indicate we're in EASY OMF (hah!) format 1326: static const char easy_omf[] = { 0x80,0xAA,'8','0','3','8','6' };
warning C4309: 'initializing' : truncation of constant value
warning C4309: 'initializing' : truncation of constant value
1327: objrecord(COMENT,easy_omf,sizeof(easy_omf)); 1328: } 1329: } 1330: 1331: // Send out a comment record showing what memory model was used 1332: comment[2] = config.target_cpu + '0'; 1333: comment[3] = model[config.memmodel]; 1334: if (I32) 1335: { if (config.exe == EX_NT) 1336: comment[3] = 'n'; 1337: else if (config.exe == EX_OS2) 1338: comment[3] = 'f'; 1339: else 1340: comment[3] = 'x'; 1341: } 1342: objrecord(COMENT,comment,sizeof(comment)); 1343: 1344: // Send out comment indicating we're using extensions to .OBJ format 1345: if (config.exe == EX_OS2) 1346: objrecord(COMENT,pmdeb,sizeof(pmdeb)); 1347: else 1348: objrecord(COMENT,exten,sizeof(exten)); 1349: 1350: // Change DGROUP to FLAT if we are doing flat memory model 1351: // (Watch out, objheader() is called twice!) 1352: if (config.exe & EX_flat) 1353: { 1354: if (lnames[2] != 'F') // do not do this twice 1355: { memcpy(lnames + 1,"\04FLAT",5); 1356: memmove(lnames + 6,lnames + 8,sizeof(lnames) - 8); 1357: } 1358: lnamesize -= 2; 1359: texti -= 2; 1360: } 1361: 1362: // Put out segment and group names 1363: if (csegname) 1364: { char *p; 1365: size_t i; 1366: 1367: // Replace the module name _TEXT with the new code segment name 1368: i = strlen(csegname); 1369: p = (char *)alloca(lnamesize + i - 5);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1370: memcpy(p,lnames,8); 1371: p[texti] = i; 1372: texti++; 1373: memcpy(p + texti,csegname,i); 1374: memcpy(p + texti + i,lnames + texti + 5,lnamesize - (texti + 5)); 1375: objrecord(LNAMES,p,lnamesize + i - 5); 1376: } 1377: else 1378: objrecord(LNAMES,lnames,lnamesize); 1379: } 1380: 1381: /******************************** 1382: * Convert module name to code segment name. 1383: * Output: 1384: * mem_malloc'd code seg name 1385: */ 1386: 1387: STATIC char * objmodtoseg(const char *modname) 1388: { char *csegname = NULL; 1389: 1390: if (LARGECODE) // if need to add in module name 1391: { int i; 1392: char *m; 1393: static const char suffix[] = "_TEXT"; 1394: 1395: // Prepend the module name to the beginning of the _TEXT 1396: m = filespecgetroot(filespecname(modname)); 1397: strupr(m);
warning C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strupr. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(252) : see declaration of 'strupr'
1398: i = strlen(m); 1399: csegname = (char *)mem_malloc(i + sizeof(suffix)); 1400: strcpy(csegname,m);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
1401: strcat(csegname,suffix);
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(110) : see declaration of 'strcat'
1402: mem_free(m); 1403: } 1404: return csegname; 1405: } 1406: 1407: /********************************* 1408: * Put out a segment definition. 1409: */ 1410: 1411: STATIC void objsegdef(int attr,targ_size_t size,int segnamidx,int classnamidx) 1412: { 1413: unsigned reclen; 1414: char sd[1+4+2+2+2+1]; 1415: 1416: //printf("objsegdef(attr=x%x, size=x%x, segnamidx=x%x, classnamidx=x%x)\n", 1417: //attr,size,segnamidx,classnamidx); 1418: sd[0] = attr; 1419: if (attr & 1 || config.flags & CFGeasyomf) 1420: { TOLONG(sd + 1,size); // store segment size 1421: reclen = 5; 1422: } 1423: else 1424: { 1425: #ifdef DEBUG 1426: assert(size <= 0xFFFF); 1427: #endif 1428: TOWORD(sd + 1,size); 1429: reclen = 3; 1430: } 1431: reclen += insidx(sd + reclen,segnamidx); // segment name index 1432: reclen += insidx(sd + reclen,classnamidx); // class name index 1433: sd[reclen] = 1; // overlay name index 1434: reclen++; 1435: if (attr & 1) // if USE32 1436: { 1437: if (config.flags & CFGeasyomf) 1438: { // Translate to Pharlap format 1439: sd[0] &= ~1; // turn off P bit 1440: 1441: // Translate A: 4->6 1442: attr &= SEG_ATTR(7,0,0,0); 1443: if (attr == SEG_ATTR(4,0,0,0)) 1444: sd[0] ^= SEG_ATTR(4 ^ 6,0,0,0); 1445: 1446: // 2 is execute/read 1447: // 3 is read/write 1448: // 4 is use32 1449: sd[reclen] = (classnamidx == 4) ? (4+2) : (4+3); 1450: reclen++; 1451: } 1452: } 1453: else // 16 bit segment 1454: { 1455: #if MARS 1456: assert(0); 1457: #else 1458: if (size & ~0xFFFFL) 1459: { if (size == 0x10000) // if exactly 64Kb 1460: sd[0] |= 2; // set "B" bit 1461: else 1462: synerr(EM_seg_gt_64k,size); // segment exceeds 64Kb 1463: } 1464: //printf("attr = %x\n", attr); 1465: #endif 1466: } 1467: #ifdef DEBUG 1468: assert(reclen <= sizeof(sd)); 1469: #endif 1470: objrecord(SEGDEF + (sd[0] & 1),sd,reclen); 1471: } 1472: 1473: /********************************* 1474: * Output segment and group definitions. 1475: * Input: 1476: * codesize size of code segment 1477: * datasize size of initialized data segment 1478: * cdatasize size of initialized const data segment 1479: * udatasize size of uninitialized data segment 1480: */ 1481: 1482: void objseggrp(targ_size_t codesize,targ_size_t datasize, 1483: targ_size_t cdatasize,targ_size_t udatasize) 1484: { 1485: int dsegattr; 1486: int dsymattr; 1487: 1488: // Group into DGROUP the segments CONST, _BSS and _DATA 1489: // For FLAT model, it's just GROUP FLAT 1490: static const char grpdef[] = {2,0xFF,2,0xFF,3,0xFF,4};
warning C4309: 'initializing' : truncation of constant value
warning C4309: 'initializing' : truncation of constant value
warning C4309: 'initializing' : truncation of constant value
1491: 1492: objsegdef(obj.csegattr,codesize,3,4); // seg _TEXT, class CODE 1493: 1494: #if MARS 1495: dsegattr = I32 1496: ? SEG_ATTR(SEG_ALIGN16,SEG_C_PUBLIC,0,USE32) 1497: : SEG_ATTR(SEG_ALIGN16,SEG_C_PUBLIC,0,USE16); 1498: #else 1499: dsegattr = I32 1500: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1501: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1502: #endif 1503: 1504: objsegdef(dsegattr,datasize,5,DATACLASS); // seg _DATA, class DATA 1505: objsegdef(dsegattr,cdatasize,7,7); // seg CONST, class CONST 1506: objsegdef(dsegattr,udatasize,8,9); // seg _BSS, class BSS 1507: 1508: obj.lnameidx = 10; // next lname index 1509: obj.segidx = 5; // next segment index 1510: 1511: if (config.fulltypes) 1512: { 1513: dsymattr = I32 1514: ? SEG_ATTR(SEG_ALIGN1,SEG_C_ABS,0,USE32) 1515: : SEG_ATTR(SEG_ALIGN1,SEG_C_ABS,0,USE16); 1516: 1517: if (config.exe & EX_flat) 1518: { // IBM's version of CV uses dword aligned segments 1519: dsymattr = SEG_ATTR(SEG_ALIGN4,SEG_C_ABS,0,USE32); 1520: } 1521: else if (config.fulltypes == CV4) 1522: { // Always use 32 bit segments 1523: dsymattr |= USE32; 1524: assert(!(config.flags & CFGeasyomf)); 1525: } 1526: objsegdef(dsymattr,SegData[DEBSYM]->SDoffset,0x0C,0x0D); 1527: objsegdef(dsymattr,SegData[DEBTYP]->SDoffset,0x0A,0x0B); 1528: obj.lnameidx += 4; // next lname index 1529: obj.segidx += 2; // next segment index 1530: } 1531: 1532: objrecord(GRPDEF,grpdef,(config.exe & EX_flat) ? 1 : sizeof(grpdef)); 1533: #if 0 1534: // Define fixup threads, we don't use them 1535: { static const char thread[] = { 0,3,1,2,2,1,3,4,0x40,1,0x45,1 }; 1536: objrecord(obj.mfixupp,thread,sizeof(thread)); 1537: } 1538: // This comment appears to indicate that no more PUBDEFs, EXTDEFs, 1539: // or COMDEFs are coming. 1540: { static const char cv[] = {0,0xA2,1}; 1541: objrecord(COMENT,cv,sizeof(cv)); 1542: } 1543: #endif 1544: } 1545: 1546: //#if NEWSTATICDTOR 1547: 1548: /************************************** 1549: * Symbol is the function that calls the static constructors. 1550: * Put a pointer to it into a special segment that the startup code 1551: * looks at. 1552: * Input: 1553: * s static constructor function 1554: * dtor number of static destructors 1555: * seg 1: user 1556: * 2: lib 1557: * 3: compiler 1558: */ 1559: 1560: void obj_staticctor(Symbol *s,int dtor,int seg) 1561: { 1562: // We need to always put out the segments in triples, so that the 1563: // linker will put them in the correct order. 1564: static char lnamector[] = "\05XIFCB\04XIFU\04XIFL\04XIFM\05XIFCE"; 1565: static char lnamedtor[] = "\04XOFB\03XOF\04XOFE"; 1566: static char lnamedtorf[] = "\03XOB\02XO\03XOE"; 1567: 1568: int dsegattr; 1569: int i; 1570: 1571: symbol_debug(s); 1572: 1573: // Determine if near or far function 1574: assert(I32 || tyfarfunc(s->ty())); 1575: 1576: // Put out LNAMES record 1577: objrecord(LNAMES,lnamector,sizeof(lnamector) - 1); 1578: 1579: dsegattr = I32 1580: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1581: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1582: 1583: for (i = 0; i < 5; i++) 1584: { int sz; 1585: 1586: sz = (i == seg) ? 4 : 0; 1587: 1588: // Put out segment definition record 1589: objsegdef(dsegattr,sz,obj.lnameidx,DATACLASS); 1590: 1591: if (i == seg) 1592: reftoident(obj.segidx,0,s,0,0); // put out function pointer 1593: 1594: obj.lnameidx++; 1595: 1596: seg_data *pseg = getsegment(); 1597: pseg->SDseg = obj.segidx++; 1598: } 1599: 1600: if (dtor) 1601: { // Leave space in XOF segment so that __fatexit() can insert a 1602: // pointer to the static destructor in XOF. 1603: 1604: // Put out LNAMES record 1605: if (LARGEDATA) 1606: objrecord(LNAMES,lnamedtorf,sizeof(lnamedtorf) - 1); 1607: else 1608: objrecord(LNAMES,lnamedtor,sizeof(lnamedtor) - 1); 1609: 1610: // Put out beginning segment 1611: objsegdef(dsegattr,0,obj.lnameidx,BSSCLASS); 1612: 1613: // Put out segment definition record 1614: objsegdef(dsegattr,4 * dtor,obj.lnameidx + 1,BSSCLASS); 1615: 1616: // Put out ending segment 1617: objsegdef(dsegattr,0,obj.lnameidx + 2,BSSCLASS); 1618: 1619: obj.lnameidx += 3; // for next time 1620: obj.segidx += 3; 1621: } 1622: } 1623: 1624: //#else 1625: 1626: /*************************************** 1627: * Stuff pointer to function in its own segment. 1628: * Used for static ctor and dtor lists. 1629: */ 1630: 1631: void obj_funcptr(Symbol *s) 1632: { 1633: // We need to always put out the segments in triples, so that the 1634: // linker will put them in the correct order. 1635: static char lnames[4][5+4+5+1] = 1636: { "\03XIB\02XI\03XIE", // near constructor 1637: "\03XCB\02XC\03XCE", // near destructor 1638: "\04XIFB\03XIF\04XIFE", // far constructor 1639: "\04XCFB\03XCF\04XCFE", // far destructor 1640: }; 1641: // Size of each of the above strings 1642: static int lnamesize[4] = { 4+3+4,4+3+4,5+4+5,5+4+5 }; 1643: 1644: int dsegattr; 1645: int i; 1646: 1647: symbol_debug(s); 1648: #ifdef DEBUG 1649: assert(memcmp(s->Sident,"_ST",3) == 0); 1650: #endif 1651: 1652: // Determine if constructor or destructor 1653: // _STI... is a constructor, _STD... is a destructor 1654: i = s->Sident[3] == 'D'; 1655: // Determine if near or far function 1656: if (tyfarfunc(s->Stype->Tty)) 1657: i += 2; 1658: 1659: // Put out LNAMES record 1660: objrecord(LNAMES,lnames[i],lnamesize[i]); 1661: 1662: dsegattr = I32 1663: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1664: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1665: 1666: // Put out beginning segment 1667: objsegdef(dsegattr,0,obj.lnameidx,DATACLASS); 1668: obj.segidx++; 1669: 1670: // Put out segment definition record 1671: // size is NPTRSIZE or FPTRSIZE 1672: objsegdef(dsegattr,(i & 2) + tysize[TYnptr],obj.lnameidx + 1,DATACLASS); 1673: seg_data *pseg = getsegment(); 1674: pseg->SDseg = obj.segidx; 1675: reftoident(obj.segidx,0,s,0,0); // put out function pointer 1676: obj.segidx++; 1677: 1678: // Put out ending segment 1679: objsegdef(dsegattr,0,obj.lnameidx + 2,DATACLASS); 1680: obj.segidx++; 1681: 1682: obj.lnameidx += 3; // for next time 1683: } 1684: 1685: //#endif 1686: 1687: /*************************************** 1688: * Stuff pointer to function in its own segment. 1689: * Used for static ctor and dtor lists. 1690: */ 1691: 1692: void obj_ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) 1693: { 1694: // We need to always put out the segments in triples, so that the 1695: // linker will put them in the correct order. 1696: static char lnames[] = 1697: { "\03FIB\02FI\03FIE" // near constructor 1698: }; 1699: int i;
warning C4101: 'i' : unreferenced local variable
1700: int dsegattr; 1701: targ_size_t offset; 1702: 1703: symbol_debug(sfunc); 1704: 1705: if (obj.fiseg == 0) 1706: { 1707: // Put out LNAMES record 1708: objrecord(LNAMES,lnames,sizeof(lnames) - 1); 1709: 1710: dsegattr = I32 1711: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1712: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1713: 1714: // Put out beginning segment 1715: objsegdef(dsegattr,0,obj.lnameidx,DATACLASS); 1716: obj.lnameidx++; 1717: obj.segidx++; 1718: 1719: // Put out segment definition record 1720: obj.fisegi = obj_newfarseg(0,DATACLASS); 1721: objsegdef(dsegattr,0,obj.lnameidx,DATACLASS); 1722: SegData[obj.fisegi]->attr = dsegattr; 1723: obj.fiseg = obj.segidx; 1724: 1725: // Put out ending segment 1726: objsegdef(dsegattr,0,obj.lnameidx + 1,DATACLASS); 1727: 1728: obj.lnameidx += 2; // for next time 1729: obj.segidx += 2; 1730: } 1731: offset = SegData[obj.fisegi]->SDoffset; 1732: offset += reftoident(obj.fiseg,offset,sfunc,0,LARGECODE ? CFoff | CFseg : CFoff); // put out function pointer 1733: offset += reftoident(obj.fiseg,offset,ehsym,0,0); // pointer to data 1734: obj_bytes(obj.fiseg,offset,intsize,&size); // size of function 1735: SegData[obj.fisegi]->SDoffset = offset + intsize; 1736: } 1737: 1738: /*************************************** 1739: * Append pointer to ModuleInfo to "FM" segment. 1740: * The FM segment is bracketed by the empty FMB and FME segments. 1741: */ 1742: 1743: #if MARS 1744: 1745: void obj_moduleinfo(Symbol *scc) 1746: { 1747: // We need to always put out the segments in triples, so that the 1748: // linker will put them in the correct order. 1749: static char lnames[] = 1750: { "\03FMB\02FM\03FME" 1751: }; 1752: int i;
warning C4101: 'i' : unreferenced local variable
1753: int dsegattr; 1754: targ_size_t offset; 1755: 1756: symbol_debug(scc); 1757: 1758: if (obj.fmseg == 0) 1759: { 1760: // Put out LNAMES record 1761: objrecord(LNAMES,lnames,sizeof(lnames) - 1); 1762: 1763: dsegattr = I32 1764: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1765: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1766: 1767: // Put out beginning segment 1768: objsegdef(dsegattr,0,obj.lnameidx,DATACLASS); 1769: obj.lnameidx++; 1770: obj.segidx++; 1771: 1772: // Put out segment definition record 1773: obj.fmsegi = obj_newfarseg(0,DATACLASS); 1774: objsegdef(dsegattr,0,obj.lnameidx,DATACLASS); 1775: SegData[obj.fmsegi]->attr = dsegattr; 1776: obj.fmseg = obj.segidx; 1777: 1778: // Put out ending segment 1779: objsegdef(dsegattr,0,obj.lnameidx + 1,DATACLASS); 1780: 1781: obj.lnameidx += 2; // for next time 1782: obj.segidx += 2; 1783: } 1784: offset = SegData[obj.fmsegi]->SDoffset; 1785: offset += reftoident(obj.fmseg,offset,scc,0,LARGECODE ? CFoff | CFseg : CFoff); // put out function pointer 1786: SegData[obj.fmsegi]->SDoffset = offset; 1787: } 1788: 1789: #endif 1790: 1791: 1792: /********************************* 1793: * Setup for Symbol s to go into a COMDAT segment. 1794: * Output (if s is a function): 1795: * cseg segment index of new current code segment 1796: * Coffset starting offset in cseg 1797: * Returns: 1798: * "segment index" of COMDAT (which will be a negative value to 1799: * distinguish it from regular segments). 1800: */ 1801: 1802: int obj_comdat(Symbol *s) 1803: { char lnames[IDMAX+IDOHD+1]; // +1 to allow room for strcpy() terminating 0 1804: char cextdef[2+2]; 1805: char __ss *p; 1806: size_t lnamesize; 1807: unsigned ti; 1808: int isfunc; 1809: tym_t ty; 1810: 1811: symbol_debug(s); 1812: ty = s->ty(); 1813: isfunc = tyfunc(ty) != 0; 1814: 1815: // Put out LNAME for name of Symbol 1816: lnamesize = obj_mangle(s,lnames); 1817: objrecord((s->Sclass == SCstatic ? LLNAMES : LNAMES),lnames,lnamesize); 1818: 1819: // Put out CEXTDEF for name of Symbol 1820: outextdata(); 1821: p = cextdef; 1822: p += insidx(p,obj.lnameidx++); 1823: ti = (config.fulltypes == CVOLD) ? cv_typidx(s->Stype) : 0; 1824: p += instypidx(p,ti); 1825: objrecord(CEXTDEF,cextdef,p - cextdef); 1826: s->Sxtrnnum = ++obj.extidx; 1827: 1828: // Start new LEDATA record for this COMDAT 1829: ledata_new(-obj.extidx,0); 1830: obj.ledata->typidx = ti; 1831: obj.ledata->pubnamidx = obj.lnameidx - 1; 1832: if (isfunc) 1833: { obj.ledata->pubbase = cseg; 1834: if (s->Sclass == SCcomdat || s->Sclass == SCinline 1835: #if MARS 1836: //|| s->Sclass == SCglobal 1837: #endif 1838: ) 1839: obj.ledata->alloctyp = 0x10 | 0x00; // pick any instance | explicit allocation 1840: cseg = obj.ledata->lseg; 1841: obj.pubnamidx = obj.lnameidx - 1; 1842: Coffset = 0; 1843: if (tyfarfunc(ty) && strcmp(s->Sident,"main") == 0) 1844: obj.ledata->alloctyp |= 1; // because MS does for unknown reasons 1845: } 1846: else 1847: { unsigned char atyp; 1848: 1849: switch (ty & mTYLINK) 1850: { case 0: 1851: case mTYnear: obj.ledata->pubbase = DATA; 1852: #if 0 1853: atyp = 0; // only one instance is allowed 1854: #else 1855: atyp = 0x10; // pick any (also means it is 1856: // not searched for in a library) 1857: #endif 1858: break; 1859: 1860: case mTYcs: obj.ledata->flags |= 0x08; // data in code seg 1861: atyp = 0x11; break; 1862: 1863: case mTYfar: atyp = 0x12; break; 1864: 1865: case mTYthread: obj.ledata->pubbase = obj_tlsseg()->SDseg; 1866: atyp = 0x10; // pick any (also means it is 1867: // not searched for in a library) 1868: break; 1869: 1870: default: assert(0); 1871: } 1872: obj.ledata->alloctyp = atyp; 1873: } 1874: if (s->Sclass == SCstatic) 1875: obj.ledata->flags |= 0x04; // local bit (make it an "LCOMDAT") 1876: seg_data *pseg = getsegment(); 1877: pseg->SDseg = -obj.extidx; 1878: return -obj.extidx; 1879: } 1880: 1881: /********************************** 1882: * Reset code seg to existing seg. 1883: * Used after a COMDAT for a function is done. 1884: */ 1885: 1886: void obj_setcodeseg(int seg,targ_size_t offset) 1887: { 1888: assert(0 < seg && seg < obj.segidx); 1889: cseg = seg; 1890: Coffset = offset; 1891: } 1892: 1893: /******************************** 1894: * Define a new code segment. 1895: * Input: 1896: * name name of segment, if NULL then revert to default 1897: * suffix 0 use name as is 1898: * 1 append "_TEXT" to name 1899: * Output: 1900: * cseg segment index of new current code segment 1901: * Coffset starting offset in cseg 1902: * Returns: 1903: * segment index of newly created code segment 1904: */ 1905: 1906: int obj_codeseg(char *name,int suffix) 1907: { 1908: char *lnames; 1909: size_t lnamesize; 1910: 1911: if (!name) 1912: { 1913: if (cseg != CODE) 1914: { 1915: if (obj.lastfarcodesegi != -1) 1916: SegData[obj.lastfarcodesegi]->SDoffset = Coffset; 1917: obj.lastfarcodesegi = -1; 1918: Coffset = obj.codeSegOffset; 1919: cseg = CODE; 1920: } 1921: return cseg; 1922: } 1923: 1924: // Put out LNAMES record 1925: lnamesize = strlen(name) + suffix * 5; 1926: lnames = (char *) alloca(1 + lnamesize + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1927: lnames[0] = lnamesize; 1928: assert(lnamesize <= (255 - 2 - sizeof(int)*3)); 1929: strcpy(lnames + 1,name);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
1930: if (suffix) 1931: strcat(lnames + 1,"_TEXT");
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(110) : see declaration of 'strcat'
1932: objrecord(LNAMES,lnames,lnamesize + 1); 1933: 1934: if (obj.lastfarcodesegi == -1) 1935: obj.codeSegOffset = Coffset; // size of default code seg 1936: else 1937: SegData[obj.lastfarcodesegi]->SDoffset = Coffset; 1938: obj.lastfarcodesegi = obj_newfarseg(0,4); 1939: SegData[obj.lastfarcodesegi]->attr = obj.csegattr; 1940: cseg = obj.segidx; // new code segment index 1941: Coffset = 0; 1942: 1943: objsegdef(obj.csegattr,0,obj.lnameidx++,4); 1944: 1945: return obj.segidx++; 1946: } 1947: 1948: /********************************* 1949: * Define segment for Thread Local Storage. 1950: * Output: 1951: * tlsseg set to segment number for TLS segment. 1952: * Returns: 1953: * segment for TLS segment 1954: */ 1955: 1956: seg_data *obj_tlsseg_bss() { return obj_tlsseg(); } 1957: 1958: seg_data *obj_tlsseg() 1959: { //static char tlssegname[] = "\04$TLS\04$TLS"; 1960: //static char tlssegname[] = "\05.tls$\03tls"; 1961: static const char tlssegname[] = "\05.tls$\03tls\04.tls\010.tls$ZZZ"; 1962: 1963: if (obj.tlsseg == UNKNOWN) 1964: { int segattr; 1965: 1966: objrecord(LNAMES,tlssegname,sizeof(tlssegname) - 1); 1967: 1968: segattr = I32 1969: ? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32) 1970: : SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 1971: 1972: // Put out beginning segment (.tls) 1973: objsegdef(segattr,0,obj.lnameidx + 2,obj.lnameidx + 1); 1974: obj.segidx++; 1975: 1976: // Put out .tls$ segment definition record 1977: obj.tlssegi = obj_newfarseg(0,obj.lnameidx + 1); 1978: obj.tlsseg = obj.segidx; 1979: objsegdef(segattr,0,obj.lnameidx,obj.lnameidx + 1); 1980: SegData[obj.tlssegi]->attr = segattr; 1981: SegData[obj.tlssegi]->SDseg = obj.tlsseg; 1982: 1983: // Put out ending segment (.tls$ZZZ) 1984: objsegdef(segattr,0,obj.lnameidx + 3,obj.lnameidx + 1); 1985: 1986: obj.lnameidx += 4; 1987: obj.segidx += 2; 1988: } 1989: return SegData[obj.tlssegi]; 1990: } 1991: 1992: 1993: /******************************** 1994: * Define a far data segment. 1995: * Input: 1996: * name Name of module 1997: * size Size of the segment to be created 1998: * Returns: 1999: * segment index of far data segment created 2000: */ 2001: 2002: int obj_fardata(char *name,targ_size_t size,targ_size_t *poffset) 2003: { 2004: static char fardataclass[] = "\010FAR_DATA"; 2005: int len; 2006: int i; 2007: char *buffer; 2008: 2009: // See if we can use existing far segment, and just bump its size 2010: i = obj.lastfardatasegi; 2011: if (i != -1 2012: && (intsize != 2 || (unsigned long) SegData[i]->SDoffset + size < 0x8000) 2013: ) 2014: { *poffset = SegData[i]->SDoffset; // BUG: should align this 2015: SegData[i]->SDoffset += size; 2016: return SegData[i]->seg; 2017: } 2018: 2019: // No. We need to build a new far segment 2020: 2021: if (obj.fardataidx == 0) // if haven't put out far data lname 2022: { // Put out class lname 2023: objrecord(LNAMES,fardataclass,sizeof(fardataclass) - 1); 2024: obj.fardataidx = obj.lnameidx++; 2025: } 2026: 2027: // Generate name based on module name 2028: name = strupr(filespecgetroot(filespecname(obj.modname)));
warning C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strupr. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(252) : see declaration of 'strupr'
2029: 2030: // Generate name for this far segment 2031: len = 1 + strlen(name) + 3 + 5 + 1; 2032: buffer = (char *)alloca(len);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
2033: sprintf(buffer + 1,"%s%d_DATA",name,obj.segidx);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2034: len = strlen(buffer + 1); 2035: buffer[0] = len; 2036: assert(len <= 255); 2037: objrecord(LNAMES,buffer,len + 1); 2038: 2039: mem_free(name); 2040: 2041: // Construct a new SegData[] entry 2042: obj.lastfardatasegi = obj_newfarseg(size,obj.fardataidx); 2043: 2044: // Generate segment definition 2045: objsegdef(obj.fdsegattr,size,obj.lnameidx++,obj.fardataidx); 2046: 2047: *poffset = 0; 2048: return obj.segidx++; 2049: } 2050: 2051: /************************************ 2052: * Remember where we put a far segment so we can adjust 2053: * its size later. 2054: * Input: 2055: * obj.segidx 2056: * lnameidx 2057: * Returns: 2058: * index of SegData[] 2059: */ 2060: 2061: STATIC int obj_newfarseg(targ_size_t size,int classidx) 2062: { 2063: #if 1 2064: seg_data *f; 2065: f = getsegment(); 2066: int i = seg_count; 2067: f->SDseg = obj.segidx; 2068: #else 2069: int i = obj.farsegi++; 2070: Farseg *f; 2071: 2072: obj.farseg = (Farseg *) mem_realloc(obj.farseg,sizeof(Farseg) * obj.farsegi); 2073: f = &SegData[i]; 2074: #endif 2075: f->isfarseg = true; 2076: f->seek = obj.buf->size(); 2077: f->seg = obj.segidx; 2078: f->attr = obj.fdsegattr; 2079: f->origsize = size; 2080: f->SDoffset = size; 2081: f->lnameidx = obj.lnameidx; 2082: f->classidx = classidx; 2083: return i; 2084: } 2085: 2086: /****************************** 2087: * Convert reference to imported name. 2088: */ 2089: 2090: void obj_import(elem *e) 2091: { 2092: #if MARS 2093: assert(0); 2094: #else 2095: Symbol *s; 2096: Symbol *simp; 2097: 2098: elem_debug(e); 2099: if ((e->Eoper == OPvar || e->Eoper == OPrelconst) && 2100: (s = e->EV.sp.Vsym)->ty() & mTYimport && 2101: (s->Sclass == SCextern || s->Sclass == SCinline) 2102: ) 2103: { char *name; 2104: char *p; 2105: size_t len; 2106: char buffer[IDMAX + IDOHD + 1]; 2107: 2108: // Create import name 2109: len = obj_mangle(s,buffer); 2110: if (buffer[0] == (char)0xFF && buffer[1] == 0) 2111: { name = buffer + 4; 2112: len -= 4; 2113: } 2114: else 2115: { name = buffer + 1; 2116: len -= 1; 2117: } 2118: if (config.flags4 & CFG4underscore) 2119: { p = (char *) alloca(5 + len + 1); 2120: memcpy(p,"_imp_",5); 2121: memcpy(p + 5,name,len); 2122: p[5 + len] = 0; 2123: } 2124: else 2125: { p = (char *) alloca(6 + len + 1); 2126: memcpy(p,"__imp_",6); 2127: memcpy(p + 6,name,len); 2128: p[6 + len] = 0; 2129: } 2130: simp = scope_search(p,SCTglobal); 2131: if (!simp) 2132: { type *t; 2133: 2134: simp = scope_define(p,SCTglobal,SCextern); 2135: simp->Ssequence = 0; 2136: simp->Sfl = FLextern; 2137: simp->Simport = s; 2138: t = newpointer(s->Stype); 2139: t->Tmangle = mTYman_c; 2140: t->Tcount++; 2141: simp->Stype = t; 2142: } 2143: assert(!e->EV.sp.Voffset); 2144: if (e->Eoper == OPrelconst) 2145: { 2146: e->Eoper = OPvar; 2147: e->EV.sp.Vsym = simp; 2148: } 2149: else // OPvar 2150: { 2151: e->Eoper = OPind; 2152: e->E1 = el_var(simp); 2153: e->E2 = NULL; 2154: } 2155: } 2156: #endif 2157: } 2158: 2159: /******************************* 2160: * Mangle a name. 2161: * Returns: 2162: * length of mangled name 2163: */ 2164: 2165: size_t obj_mangle(Symbol *s,char *dest) 2166: { size_t len; 2167: size_t ilen; 2168: char *name; 2169: char *name2 = NULL; 2170: 2171: //printf("obj_mangle('%s'), mangle = x%x\n",s->Sident,type_mangle(s->Stype)); 2172: #if SCPP 2173: name = CPP ? cpp_mangle(s) : s->Sident; 2174: #elif MARS 2175: name = cpp_mangle(s); 2176: #else 2177: name = s->Sident; 2178: #endif 2179: len = strlen(name); // # of bytes in name 2180: 2181: // Use as max length the max length lib.exe can handle 2182: // Use 5 as length of _ + @nnn 2183: #define LIBIDMAX ((512 - 0x25 - 3 - 4) - 5) 2184: #define LIBIDMAX 128
warning C4005: 'LIBIDMAX' : macro redefinition backend\cgobj.c(2183) : see previous definition of 'LIBIDMAX'
2185: if (len > LIBIDMAX) 2186: //if (len > IDMAX) 2187: { 2188: size_t len2; 2189: 2190: // Attempt to compress the name 2191: name2 = id_compress(name, len); 2192: len2 = strlen(name2); 2193: #if MARS 2194: if (len2 > LIBIDMAX) // still too long 2195: { 2196: /* Form md5 digest of the name and store it in the 2197: * last 32 bytes of the name. 2198: */ 2199: MD5_CTX mdContext; 2200: MD5Init(&mdContext); 2201: MD5Update(&mdContext, (unsigned char *)name, len); 2202: MD5Final(&mdContext); 2203: memcpy(name2, name, LIBIDMAX - 32); 2204: for (int i = 0; i < 16; i++) 2205: { unsigned char c = mdContext.digest[i]; 2206: unsigned char c1 = (c >> 4) & 0x0F; 2207: unsigned char c2 = c & 0x0F; 2208: c1 += (c1 < 10) ? '0' : 'A' - 10; 2209: name2[LIBIDMAX - 32 + i * 2] = c1; 2210: c2 += (c2 < 10) ? '0' : 'A' - 10; 2211: name2[LIBIDMAX - 32 + i * 2 + 1] = c2; 2212: } 2213: name = name2; 2214: len = LIBIDMAX; 2215: name[len] = 0; 2216: //printf("name = '%s', len = %d, strlen = %d\n", name, len, strlen(name)); 2217: } 2218: #else 2219: if (len2 > IDMAX) // still too long 2220: { 2221: #if SCPP 2222: synerr(EM_identifier_too_long, name, len - IDMAX, IDMAX); 2223: #elif MARS 2224: // error(0, "identifier %s is too long by %d characters", name, len - IDMAX); 2225: #else 2226: assert(0); 2227: #endif 2228: len = IDMAX; 2229: } 2230: #endif 2231: else 2232: { 2233: name = name2; 2234: len = len2; 2235: } 2236: } 2237: ilen = len; 2238: if (ilen > (255-2-sizeof(int)*3)) 2239: dest += 3; 2240: switch (type_mangle(s->Stype)) 2241: { case mTYman_pas: // if upper case 2242: case mTYman_for: 2243: memcpy(dest + 1,name,len); // copy in name 2244: dest[1 + len] = 0; 2245: strupr(dest + 1); // to upper case
warning C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strupr. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(252) : see declaration of 'strupr'
2246: break; 2247: #if SCPP || MARS 2248: case mTYman_cpp: 2249: #if NEWMANGLE 2250: memcpy(dest + 1,name,len); 2251: break; 2252: #endif 2253: #endif 2254: case mTYman_std: 2255: if (!(config.flags4 & CFG4oldstdmangle) && 2256: config.exe == EX_NT && tyfunc(s->ty()) && 2257: !variadic(s->Stype)) 2258: { 2259: dest[1] = '_'; 2260: memcpy(dest + 2,name,len); 2261: dest[1 + 1 + len] = '@'; 2262: itoa(type_paramsize(s->Stype),dest + 3 + len,10);
warning C4996: 'itoa': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _itoa. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(867) : see declaration of 'itoa'
2263: len = strlen(dest + 1); 2264: assert(isdigit(dest[len]));
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isdigit'
2265: break; 2266: } 2267: case mTYman_c: 2268: if (config.flags4 & CFG4underscore) 2269: { 2270: dest[1] = '_'; // leading _ in name 2271: memcpy(&dest[2],name,len); // copy in name 2272: len++; 2273: break; 2274: } 2275: case mTYman_d: 2276: case mTYman_sys: 2277: memcpy(dest + 1, name, len); // no mangling 2278: dest[1 + len] = 0; 2279: break; 2280: default: 2281: #ifdef DEBUG 2282: symbol_print(s); 2283: #endif 2284: assert(0); 2285: } 2286: if (ilen > (255-2-sizeof(int)*3)) 2287: { dest -= 3; 2288: dest[0] = 0xFF;
warning C4309: '=' : truncation of constant value
2289: dest[1] = 0; 2290: #ifdef DEBUG 2291: assert(len <= 0xFFFF); 2292: #endif 2293: TOWORD(dest + 2,len); 2294: len += 4; 2295: } 2296: else 2297: { *dest = len; 2298: len++; 2299: } 2300: if (name2) 2301: free(name2); 2302: assert(len <= IDMAX + IDOHD); 2303: return len; 2304: } 2305: 2306: /******************************* 2307: * Export a function name. 2308: */ 2309: 2310: void obj_export(Symbol *s,unsigned argsize) 2311: { char *coment; 2312: size_t len; 2313: 2314: coment = (char *) alloca(4 + 1 + (IDMAX + IDOHD) + 1); // allow extra byte for mangling
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
2315: len = obj_mangle(s,&coment[4]); 2316: assert(len <= IDMAX + IDOHD); 2317: coment[1] = 0xA0; // comment class
warning C4309: '=' : truncation of constant value
2318: coment[2] = 2; // why??? who knows 2319: if (argsize >= 64) // we only have a 5 bit field 2320: argsize = 0; // hope we don't need callgate 2321: coment[3] = (argsize + 1) >> 1; // # words on stack 2322: coment[4 + len] = 0; // no internal name 2323: objrecord(COMENT,coment,4 + len + 1); // module name record 2324: } 2325: 2326: /******************************** 2327: * Output a public definition. 2328: * Input: 2329: * seg = segment index that symbol is defined in 2330: * s -> symbol 2331: * offset = offset of name 2332: */ 2333: 2334: STATIC void outpubdata() 2335: { 2336: if (obj.pubdatai) 2337: { objrecord(obj.mpubdef,obj.pubdata,obj.pubdatai); 2338: obj.pubdatai = 0; 2339: } 2340: } 2341: 2342: void objpubdef(int seg,Symbol *s,targ_size_t offset) 2343: { unsigned reclen,len; 2344: char *p; 2345: unsigned ti; 2346: 2347: _chkstack(); 2348: 2349: if (obj.pubdatai + 1 + (IDMAX + IDOHD) + 4 + 2 > sizeof(obj.pubdata) || 2350: seg != getindex(obj.pubdata + 1)) 2351: outpubdata(); 2352: if (obj.pubdatai == 0) 2353: { 2354: obj.pubdata[0] = (seg == DATA || seg == UDATA) ? 1 : 0; // group index 2355: obj.pubdatai += 1 + insidx(obj.pubdata + 1,seg); // segment index 2356: } 2357: p = &obj.pubdata[obj.pubdatai]; 2358: len = obj_mangle(s,p); // mangle in name 2359: reclen = len + intsize; 2360: p += len; 2361: TOOFFSET(p,offset); 2362: p += intsize; 2363: ti = (config.fulltypes == CVOLD) ? cv_typidx(s->Stype) : 0; 2364: reclen += instypidx(p,ti); 2365: obj.pubdatai += reclen; 2366: } 2367: 2368: /******************************* 2369: * Output an external definition. 2370: * Input: 2371: * name -> external identifier 2372: * Returns: 2373: * External index of the definition (1,2,...) 2374: */ 2375: 2376: STATIC void outextdata() 2377: { 2378: if (obj.extdatai) 2379: { objrecord(EXTDEF,obj.extdata,obj.extdatai); 2380: obj.extdatai = 0; 2381: } 2382: } 2383: 2384: int objextdef(const char *name) 2385: { unsigned len; 2386: char *e; 2387: 2388: _chkstack(); 2389: //dbg_printf("objextdef('%s')\n",name); 2390: assert(name); 2391: len = strlen(name); // length of identifier 2392: if (obj.extdatai + len + ONS_OHD + 1 > sizeof(obj.extdata)) 2393: outextdata(); 2394: 2395: e = &obj.extdata[obj.extdatai]; 2396: len = obj_namestring(e,name); 2397: e[len] = 0; // typidx = 0 2398: obj.extdatai += len + 1; 2399: assert(obj.extdatai <= sizeof(obj.extdata)); 2400: return ++obj.extidx; 2401: } 2402: 2403: /******************************* 2404: * Output an external definition. 2405: * Input: 2406: * s Symbol to do EXTDEF on 2407: * Returns: 2408: * External index of the definition (1,2,...) 2409: */ 2410: 2411: int objextern(Symbol *s) 2412: { unsigned len; 2413: char *e; 2414: 2415: _chkstack(); 2416: //dbg_printf("objextern('%s')\n",s->Sident); 2417: symbol_debug(s); 2418: if (obj.extdatai + (IDMAX + IDOHD) + 3 > sizeof(obj.extdata)) 2419: outextdata(); 2420: 2421: e = &obj.extdata[obj.extdatai]; 2422: len = obj_mangle(s,e); 2423: e[len] = 0; // typidx = 0 2424: obj.extdatai += len + 1; 2425: s->Sxtrnnum = ++obj.extidx; 2426: return obj.extidx; 2427: } 2428: 2429: /******************************* 2430: * Output a common block definition. 2431: * Input: 2432: * p -> external identifier 2433: * flag TRUE: in default data segment 2434: * FALSE: not in default data segment 2435: * size size in bytes of each elem 2436: * count number of elems 2437: * Returns: 2438: * External index of the definition (1,2,...) 2439: */ 2440: 2441: // Helper for obj_comdef() 2442: 2443: static unsigned storelength(unsigned long length,unsigned i) 2444: { 2445: obj.extdata[i] = length;
warning C4244: '=' : conversion from 'unsigned long' to 'char', possible loss of data
2446: if (length >= 128) // Microsoft docs say 129, but their linker 2447: // won't take >=128, so accommodate it 2448: { obj.extdata[i] = 129;
warning C4309: '=' : truncation of constant value
2449: #ifdef DEBUG 2450: assert(length <= 0xFFFF); 2451: #endif 2452: TOWORD(obj.extdata + i + 1,length); 2453: if (length >= 0x10000) 2454: { obj.extdata[i] = 132;
warning C4309: '=' : truncation of constant value
2455: obj.extdata[i + 3] = length >> 16;
warning C4244: '=' : conversion from 'unsigned long' to 'char', possible loss of data
2456: 2457: // Only 386 can generate lengths this big 2458: if (I32 && length >= 0x1000000) 2459: { obj.extdata[i] = 136;
warning C4309: '=' : truncation of constant value
2460: obj.extdata[i + 4] = length >> 24; 2461: i += 4; 2462: } 2463: else 2464: i += 3; 2465: } 2466: else 2467: i += 2; 2468: } 2469: return i + 1; // index past where we stuffed length 2470: } 2471: 2472: int obj_comdef(Symbol *s,int flag,targ_size_t size,targ_size_t count) 2473: { register unsigned i; 2474: unsigned long length; 2475: unsigned ti; 2476: 2477: //dbg_printf("obj_comdef('%s',%d,%d,%d)\n",s->Sident,flag,size,count); 2478: outextdata(); // borrow the extdata[] storage 2479: i = obj_mangle(s,obj.extdata); 2480: 2481: ti = (config.fulltypes == CVOLD) ? cv_typidx(s->Stype) : 0; 2482: i += instypidx(obj.extdata + i,ti); 2483: 2484: if (flag) // if in default data segment 2485: { 2486: //printf("NEAR comdef\n"); 2487: obj.extdata[i] = 0x62; 2488: length = (unsigned long) size * count; 2489: assert(I32 || length <= 0x10000); 2490: i = storelength(length,i + 1); 2491: } 2492: else 2493: { 2494: //printf("FAR comdef\n"); 2495: obj.extdata[i] = 0x61; 2496: i = storelength((unsigned long) size,i + 1); 2497: i = storelength((unsigned long) count,i); 2498: } 2499: assert(i <= arraysize(obj.extdata)); 2500: objrecord(COMDEF,obj.extdata,i); 2501: return ++obj.extidx; 2502: } 2503: 2504: /*************************************** 2505: * Append an iterated data block of 0s. 2506: * (uninitialized data only) 2507: */ 2508: 2509: void obj_write_zeros(seg_data *pseg, targ_size_t count) 2510: { 2511: obj_lidata(pseg->SDseg, pseg->SDoffset, count); 2512: pseg->SDoffset += count; 2513: } 2514: 2515: /*************************************** 2516: * Output an iterated data block of 0s. 2517: * (uninitialized data only) 2518: */ 2519: 2520: void obj_lidata(int seg,targ_size_t offset,targ_size_t count) 2521: { int i; 2522: unsigned reclen; 2523: static char zero[20]; 2524: char data[20]; 2525: char __ss *di; 2526: 2527: //printf("obj_lidata(seg = %d, offset = x%x, count = %d)\n", seg, offset, count); 2528: if (count <= sizeof(zero)) // if shorter to use ledata 2529: { 2530: obj_bytes(seg,offset,count,zero); 2531: return; 2532: } 2533: 2534: if (seg < 0) 2535: { 2536: while (count > sizeof(zero)) 2537: { 2538: obj_bytes(seg,offset,sizeof(zero),zero); 2539: offset += sizeof(zero); 2540: count -= sizeof(zero); 2541: } 2542: obj_bytes(seg,offset,count,zero); 2543: return; 2544: } 2545: 2546: i = insidx(data,seg); 2547: di = data + i; 2548: TOOFFSET(di,offset); 2549: 2550: if (config.flags & CFGeasyomf) 2551: { 2552: if (count >= 0x8000) // repeat count can only go to 32k 2553: { 2554: TOWORD(di + 4,(unsigned short)(count / 0x8000)); 2555: TOWORD(di + 4 + 2,1); // 1 data block follows 2556: TOWORD(di + 4 + 2 + 2,0x8000); // repeat count 2557: TOWORD(di + 4 + 2 + 2 + 2,0); // block count 2558: TOWORD(di + 4 + 2 + 2 + 2 + 2,1); // 1 byte of 0 2559: reclen = i + 4 + 5 * 2; 2560: objrecord(obj.mlidata,data,reclen); 2561: obj_lidata(seg,offset + (count & ~0x7FFFL),count & 0x7FFF); 2562: } 2563: else 2564: { 2565: TOWORD(di + 4,(unsigned short)count); // repeat count 2566: TOWORD(di + 4 + 2,0); // block count 2567: TOWORD(di + 4 + 2 + 2,1); // 1 byte of 0 2568: reclen = i + 4 + 2 + 2 + 2; 2569: objrecord(obj.mlidata,data,reclen); 2570: } 2571: } 2572: else 2573: { 2574: TOOFFSET(di + intsize,count); 2575: TOWORD(di + intsize * 2,0); // block count 2576: TOWORD(di + intsize * 2 + 2,1); // repeat 1 byte of 0s 2577: reclen = i + (I32 ? 12 : 8); 2578: objrecord(obj.mlidata,data,reclen); 2579: } 2580: assert(reclen <= sizeof(data)); 2581: } 2582: 2583: /**************************** 2584: * Output a MODEND record. 2585: */ 2586: 2587: STATIC void obj_modend() 2588: { 2589: if (obj.startaddress) 2590: { char mdata[10]; 2591: int i; 2592: unsigned framedatum,targetdatum; 2593: unsigned char fd; 2594: targ_size_t offset; 2595: int external; // !=0 if identifier is defined externally 2596: tym_t ty; 2597: Symbol *s = obj.startaddress; 2598: 2599: // Turn startaddress into a fixup. 2600: // Borrow heavilly from reftoident() 2601: 2602: symbol_debug(s); 2603: offset = 0; 2604: ty = s->ty(); 2605: 2606: switch (s->Sclass) 2607: { 2608: case SCcomdat: 2609: case_SCcomdat: 2610: case SCextern: 2611: case SCcomdef: 2612: if (s->Sxtrnnum) // identifier is defined somewhere else 2613: external = s->Sxtrnnum; 2614: else 2615: { 2616: Ladd: 2617: s->Sclass = SCextern; 2618: external = objextern(s); 2619: outextdata(); 2620: } 2621: break; 2622: case SCinline: 2623: if (config.flags2 & CFG2comdat) 2624: goto case_SCcomdat; // treat as initialized common block 2625: case SCsinline: 2626: case SCstatic: 2627: case SCglobal: 2628: if (s->Sseg == UNKNOWN) 2629: goto Ladd; 2630: if (seg_is_comdat(s->Sseg)) // if in comdat 2631: goto case_SCcomdat; 2632: case SClocstat: 2633: external = 0; // identifier is static or global 2634: // and we know its offset 2635: offset += s->Soffset; 2636: break; 2637: default: 2638: #ifdef DEBUG 2639: //symbol_print(s); 2640: #endif 2641: assert(0); 2642: } 2643: 2644: if (external) 2645: { fd = FD_T2; 2646: targetdatum = external; 2647: switch (s->Sfl) 2648: { 2649: case FLextern: 2650: if (!(ty & (mTYcs | mTYthread))) 2651: goto L1; 2652: case FLfunc: 2653: case FLfardata: 2654: case FLcsdata: 2655: case FLtlsdata: 2656: if (config.exe & EX_flat) 2657: { fd |= FD_F1; 2658: framedatum = 1; 2659: } 2660: else 2661: { 2662: //case FLtlsdata: 2663: fd |= FD_F2; 2664: framedatum = targetdatum; 2665: } 2666: break; 2667: default: 2668: goto L1; 2669: } 2670: } 2671: else 2672: { 2673: fd = FD_T0; // target is always a segment 2674: targetdatum = s->Sseg; 2675: assert(targetdatum != -1); 2676: switch (s->Sfl) 2677: { 2678: case FLextern: 2679: if (!(ty & (mTYcs | mTYthread))) 2680: goto L1; 2681: case FLfunc: 2682: case FLfardata: 2683: case FLcsdata: 2684: case FLtlsdata: 2685: if (config.exe & EX_flat) 2686: { fd |= FD_F1; 2687: framedatum = 1; 2688: } 2689: else 2690: { 2691: //case FLtlsdata: 2692: fd |= FD_F0; 2693: framedatum = targetdatum; 2694: } 2695: break; 2696: default: 2697: L1: 2698: fd |= FD_F1; 2699: framedatum = DGROUPIDX; 2700: //if (flags == CFseg) 2701: { fd = FD_F1 | FD_T1; // target is DGROUP 2702: targetdatum = DGROUPIDX; 2703: } 2704: break; 2705: } 2706: } 2707: 2708: // Write the fixup into mdata[] 2709: mdata[0] = 0xC1;
warning C4309: '=' : truncation of constant value
2710: mdata[1] = fd; 2711: i = 2 + insidx(&mdata[2],framedatum); 2712: i += insidx(&mdata[i],targetdatum); 2713: TOOFFSET(mdata + i,offset); 2714: 2715: objrecord(obj.mmodend,mdata,i + intsize); // write mdata[] to .OBJ file 2716: } 2717: else 2718: { static const char modend[] = {0}; 2719: 2720: objrecord(MODEND,modend,sizeof(modend)); 2721: } 2722: } 2723: 2724: /**************************** 2725: * Output the fixups in list fl. 2726: */ 2727: 2728: STATIC void objfixupp(struct FIXUP *f) 2729: { 2730: unsigned i,j,k;
warning C4101: 'j' : unreferenced local variable
2731: targ_size_t locat; 2732: struct FIXUP *fn; 2733: 2734: #if 1 // store in one record 2735: char data[1024]; 2736: 2737: _chkstack(); 2738: i = 0; 2739: for (; f; f = fn) 2740: { unsigned char fd; 2741: 2742: if (i >= sizeof(data) - (3 + 2 + 2)) // if not enough room 2743: { objrecord(obj.mfixupp,data,i); 2744: i = 0; 2745: } 2746: 2747: //printf("f = %p, offset = x%x\n",f,f->FUoffset); 2748: assert(f->FUoffset < 1024); 2749: locat = (f->FUlcfd & 0xFF00) | f->FUoffset; 2750: data[i+0] = locat >> 8; 2751: data[i+1] = locat; 2752: data[i+2] = fd = f->FUlcfd;
warning C4244: '=' : conversion from 'unsigned short' to 'unsigned char', possible loss of data
2753: k = i; 2754: i += 3 + insidx(&data[i+3],f->FUframedatum); 2755: //printf("FUframedatum = x%x\n", f->FUframedatum); 2756: if ((fd >> 4) == (fd & 3) && f->FUframedatum == f->FUtargetdatum) 2757: { 2758: data[k + 2] = (fd & 15) | FD_F5; 2759: } 2760: else 2761: { i += insidx(&data[i],f->FUtargetdatum); 2762: //printf("FUtargetdatum = x%x\n", f->FUtargetdatum); 2763: } 2764: //printf("[%d]: %02x %02x %02x\n", k, data[k + 0] & 0xFF, data[k + 1] & 0xFF, data[k + 2] & 0xFF); 2765: fn = f->FUnext; 2766: mem_ffree(f); 2767: } 2768: assert(i <= sizeof(data)); 2769: if (i) 2770: objrecord(obj.mfixupp,data,i); 2771: #else // store in multiple records 2772: for (; fl; fl = list_next(fl)) 2773: { 2774: char data[7]; 2775: 2776: assert(f->FUoffset < 1024); 2777: locat = (f->FUlcfd & 0xFF00) | f->FUoffset; 2778: data[0] = locat >> 8; 2779: data[1] = locat; 2780: data[2] = f->FUlcfd; 2781: i = 3 + insidx(&data[3],f->FUframedatum); 2782: i += insidx(&data[i],f->FUtargetdatum); 2783: objrecord(obj.mfixupp,data,i); 2784: } 2785: #endif 2786: } 2787: 2788: 2789: /*************************** 2790: * Add a new fixup to the fixup list. 2791: * Write things out if we overflow the list. 2792: */ 2793: 2794: STATIC void addfixup(targ_size_t offset,unsigned lcfd, 2795: unsigned framedatum,unsigned targetdatum) 2796: { struct FIXUP *f; 2797: 2798: assert(offset < 0x1024); 2799: #ifdef DEBUG 2800: assert(targetdatum <= 0x7FFF); 2801: assert(framedatum <= 0x7FFF); 2802: #endif 2803: f = (struct FIXUP *) mem_fmalloc(sizeof(struct FIXUP)); 2804: //printf("f = %p, offset = x%x\n",f,offset); 2805: f->FUoffset = offset; 2806: f->FUlcfd = lcfd; 2807: f->FUframedatum = framedatum; 2808: f->FUtargetdatum = targetdatum; 2809: f->FUnext = obj.ledata->fixuplist; // link f into list 2810: obj.ledata->fixuplist = f; 2811: #ifdef DEBUG 2812: obj.fixup_count++; // gather statistics 2813: #endif 2814: } 2815: 2816: 2817: /********************************* 2818: * Open up a new ledata record. 2819: * Input: 2820: * seg segment number data is in 2821: * offset starting offset of start of data for this record 2822: */ 2823: 2824: STATIC void ledata_new(int seg,targ_size_t offset) 2825: { 2826: 2827: //dbg_printf("ledata_new(seg = %d, offset = x%lx)\n",seg,offset); 2828: assert(seg <= 0x7FFF); 2829: obj.ledata = (Ledatarec *) mem_calloc(sizeof(Ledatarec)); 2830: obj.ledata->lseg = seg; 2831: obj.ledata->offset = offset; 2832: if (seg < 0 && offset) // if continuation of an existing COMDAT 2833: { list_t dl; 2834: 2835: for (dl = obj.ledata_list; 1; dl = list_next(dl)) 2836: { Ledatarec *d; 2837: 2838: assert(dl); 2839: d = list_ledata(dl); 2840: if (d->lseg == seg) // found existing COMDAT 2841: { obj.ledata->flags = d->flags; 2842: obj.ledata->alloctyp = d->alloctyp; 2843: obj.ledata->align = d->align; 2844: obj.ledata->typidx = d->typidx; 2845: obj.ledata->pubbase = d->pubbase; 2846: obj.ledata->pubnamidx = d->pubnamidx; 2847: break; 2848: } 2849: } 2850: } 2851: list_prepend(&obj.ledata_list,obj.ledata); 2852: // list_append(&obj.ledata_list,obj.ledata); 2853: } 2854: 2855: /*********************************** 2856: * Append byte to segment. 2857: */ 2858: 2859: void obj_write_byte(seg_data *pseg, unsigned byte) 2860: { 2861: obj_byte(pseg->SDseg, pseg->SDoffset, byte); 2862: pseg->SDoffset++; 2863: } 2864: 2865: /************************************ 2866: * Output byte to object file. 2867: */ 2868: 2869: void obj_byte(int seg,targ_size_t offset,unsigned byte) 2870: { unsigned i; 2871: 2872: if ( 2873: (seg != obj.ledata->lseg || // and segments don't match 2874: obj.ledata->i > LEDATAMAX - 1 || // or it'll overflow 2875: offset < obj.ledata->offset || // underflow 2876: offset > obj.ledata->offset + obj.ledata->i 2877: ) 2878: ) 2879: { list_t dl; 2880: 2881: // Try to find an existing ledata 2882: for (dl = obj.ledata_list; dl; dl = list_next(dl)) 2883: { Ledatarec *d; 2884: 2885: d = list_ledata(dl); 2886: if (seg == d->lseg && // segments match 2887: offset >= d->offset && 2888: offset + 1 <= d->offset + LEDATAMAX && 2889: offset <= d->offset + d->i 2890: ) 2891: { 2892: obj.ledata = d; 2893: goto L1; 2894: } 2895: } 2896: ledata_new(seg,offset); 2897: L1: ; 2898: } 2899: 2900: i = offset - obj.ledata->offset; 2901: if (obj.ledata->i <= i) 2902: obj.ledata->i = i + 1; 2903: obj.ledata->data[i] = byte; // 1st byte of data
warning C6386: Buffer overrun: accessing 'obj.ledata->data', the writable size is '1010' bytes, but '-2' bytes might be written: Lines: 2870, 2873, 2879, 2882, 2896, 2897, 2900, 2901, 2903
warning C6386: Buffer overrun: accessing 'obj.ledata->data', the writable size is '1010' bytes, but '1012' bytes might be written: Lines: 2870, 2873, 2879, 2882, 2896, 2897, 2900, 2901, 2902, 2903
2904: } 2905: 2906: /*********************************** 2907: * Append bytes to segment. 2908: */ 2909: 2910: void obj_write_bytes(seg_data *pseg, unsigned nbytes, void *p) 2911: { 2912: obj_bytes(pseg->SDseg, pseg->SDoffset, nbytes, p); 2913: pseg->SDoffset += nbytes; 2914: } 2915: 2916: /************************************ 2917: * Output bytes to object file. 2918: * Returns: 2919: * nbytes 2920: */ 2921: 2922: unsigned obj_bytes(int seg,targ_size_t offset,unsigned nbytes, void *p) 2923: { unsigned n = nbytes; 2924: 2925: //dbg_printf("obj_bytes(seg=%d, offset=x%lx, nbytes=x%x, p=%p)\n",seg,offset,nbytes,p); 2926: L1: 2927: if ( 2928: (seg != obj.ledata->lseg || // and segments don't match 2929: obj.ledata->i + nbytes > LEDATAMAX || // or it'll overflow 2930: offset < obj.ledata->offset || // underflow 2931: offset > obj.ledata->offset + obj.ledata->i 2932: ) 2933: ) 2934: { 2935: while (nbytes) 2936: { obj_byte(seg,offset,*(char *)p); 2937: offset++; 2938: (*(char **)&p)++; 2939: nbytes--; 2940: if (obj.ledata->i + nbytes <= LEDATAMAX) 2941: goto L1; 2942: } 2943: } 2944: else 2945: { unsigned i; 2946: 2947: i = offset - obj.ledata->offset; 2948: if (obj.ledata->i < i + nbytes) 2949: obj.ledata->i = i + nbytes; 2950: memcpy(obj.ledata->data + i,p,nbytes); 2951: } 2952: return n; 2953: } 2954: 2955: /************************************ 2956: * Output word of data. (Two words if segment:offset pair.) 2957: * Input: 2958: * seg CODE, DATA, CDATA, UDATA 2959: * offset offset of start of data 2960: * data word of data 2961: * lcfd LCxxxx | FDxxxx 2962: * if (FD_F2 | FD_T6) 2963: * idx1 = external Symbol # 2964: * else 2965: * idx1 = frame datum 2966: * idx2 = target datum 2967: */ 2968: 2969: void objledata(int seg,targ_size_t offset,targ_size_t data, 2970: unsigned lcfd,unsigned idx1,unsigned idx2) 2971: { unsigned i; 2972: unsigned size; // number of bytes to output 2973: 2974: if ((lcfd & LOCxx) == obj.LOCpointer) 2975: size = tysize[TYfptr]; 2976: else if ((lcfd & LOCxx) == LOCbase) 2977: size = 2; 2978: else 2979: size = tysize[TYnptr]; 2980: 2981: if ( 2982: (seg != obj.ledata->lseg || // and segments don't match 2983: obj.ledata->i + size > LEDATAMAX || // or it'll overflow 2984: offset < obj.ledata->offset || // underflow 2985: offset > obj.ledata->offset + obj.ledata->i 2986: ) 2987: ) 2988: { list_t dl; 2989: 2990: // Try to find an existing ledata 2991: //dbg_printf("seg = %d, offset = x%lx, size = %d\n",seg,offset,size); 2992: for (dl = obj.ledata_list; dl; dl = list_next(dl)) 2993: { Ledatarec *d; 2994: 2995: d = list_ledata(dl); 2996: //dbg_printf("d: seg = %d, offset = x%lx, i = x%x\n",d->lseg,d->offset,d->i); 2997: if (seg == d->lseg && // segments match 2998: offset >= d->offset && 2999: offset + size <= d->offset + LEDATAMAX && 3000: offset <= d->offset + d->i 3001: ) 3002: { 3003: //dbg_printf("match\n"); 3004: obj.ledata = d; 3005: goto L1; 3006: } 3007: } 3008: ledata_new(seg,offset); 3009: L1: ; 3010: } 3011: 3012: i = offset - obj.ledata->offset; 3013: if (obj.ledata->i < i + size) 3014: obj.ledata->i = i + size; 3015: if (size == 2 || !I32) 3016: TOWORD(obj.ledata->data + i,data); 3017: else 3018: TOLONG(obj.ledata->data + i,data); 3019: if (size == tysize[TYfptr]) // if doing a seg:offset pair 3020: TOWORD(obj.ledata->data + i + tysize[TYnptr],0); // segment portion 3021: addfixup(offset - obj.ledata->offset,lcfd,idx1,idx2); 3022: } 3023: 3024: /************************************ 3025: * Output long word of data. 3026: * Input: 3027: * seg CODE, DATA, CDATA, UDATA 3028: * offset offset of start of data 3029: * data long word of data 3030: * Present only if size == 2: 3031: * lcfd LCxxxx | FDxxxx 3032: * if (FD_F2 | FD_T6) 3033: * idx1 = external Symbol # 3034: * else 3035: * idx1 = frame datum 3036: * idx2 = target datum 3037: */ 3038: 3039: void obj_long(int seg,targ_size_t offset,unsigned long data, 3040: unsigned lcfd,unsigned idx1,unsigned idx2) 3041: { unsigned i; 3042: 3043: if ( 3044: (seg != obj.ledata->lseg || // or segments don't match 3045: obj.ledata->i + tysize[TYfptr] > LEDATAMAX || // or it'll overflow 3046: offset < obj.ledata->offset || // underflow 3047: offset > obj.ledata->offset + obj.ledata->i 3048: ) 3049: ) 3050: ledata_new(seg,offset); 3051: i = offset - obj.ledata->offset; 3052: if (obj.ledata->i < i + tysize[TYfptr]) 3053: obj.ledata->i = i + tysize[TYfptr]; 3054: TOLONG(obj.ledata->data + i,data); 3055: if (I32) // if 6 byte far pointers 3056: TOWORD(obj.ledata->data + i + LONGSIZE,0); // fill out seg 3057: addfixup(offset - obj.ledata->offset,lcfd,idx1,idx2); 3058: } 3059: 3060: /******************************* 3061: * Refer to address that is in the data segment. 3062: * Input: 3063: * seg = where the address is going 3064: * offset = offset within seg 3065: * val = displacement from address 3066: * targetdatum = DATA, CDATA or UDATA, depending where the address is 3067: * flags = CFoff, CFseg 3068: * Example: 3069: * int *abc = &def[3]; 3070: * to allocate storage: 3071: * reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 3072: */ 3073: 3074: void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 3075: unsigned targetdatum,int flags) 3076: { 3077: assert(flags); 3078: 3079: if (flags == 0 || flags & CFoff) 3080: { 3081: // The frame datum is always 1, which is DGROUP 3082: objledata(seg,offset,val, 3083: LOCATsegrel | obj.LOCoffset | FD_F1 | FD_T4,DGROUPIDX,targetdatum); 3084: offset += intsize; 3085: } 3086: 3087: if (flags & CFseg) 3088: { 3089: #if 0 3090: if (config.wflags & WFdsnedgroup) 3091: warerr(WM_ds_ne_dgroup); 3092: #endif 3093: objledata(seg,offset,0, 3094: LOCATsegrel | LOCbase | FD_F1 | FD_T5,DGROUPIDX,DGROUPIDX); 3095: } 3096: } 3097: 3098: /******************************* 3099: * Refer to address that is in a far segment. 3100: * Input: 3101: * seg = where the address is going 3102: * offset = offset within seg 3103: * val = displacement from address 3104: * farseg = far segment index 3105: * flags = CFoff, CFseg 3106: */ 3107: 3108: void reftofarseg(int seg,targ_size_t offset,targ_size_t val, 3109: int farseg,int flags) 3110: { 3111: assert(flags); 3112: 3113: if (flags == 0 || flags & CFoff) 3114: { 3115: objledata(seg,offset,val, 3116: LOCATsegrel | obj.LOCoffset | FD_F0 | FD_T4,farseg,farseg); 3117: offset += intsize; 3118: } 3119: 3120: if (flags & CFseg) 3121: { 3122: objledata(seg,offset,0, 3123: LOCATsegrel | LOCbase | FD_F0 | FD_T4,farseg,farseg); 3124: } 3125: } 3126: 3127: /******************************* 3128: * Refer to address that is in the code segment. 3129: * Only offsets are output, regardless of the memory model. 3130: * Used to put values in switch address tables. 3131: * Input: 3132: * seg = where the address is going (CODE or DATA) 3133: * offset = offset within seg 3134: * val = displacement from start of this module 3135: */ 3136: 3137: void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 3138: { unsigned framedatum; 3139: unsigned lcfd; 3140: int idx; 3141: 3142: idx = cseg; 3143: if (seg_is_comdat(idx)) // if comdat 3144: { idx = -idx; 3145: framedatum = idx; 3146: lcfd = (LOCATsegrel | obj.LOCoffset) | (FD_F2 | FD_T6); 3147: } 3148: else if (config.exe & EX_flat) 3149: { framedatum = 1; 3150: lcfd = (LOCATsegrel | obj.LOCoffset) | (FD_F1 | FD_T4); 3151: } 3152: else 3153: { framedatum = idx; 3154: lcfd = (LOCATsegrel | obj.LOCoffset) | (FD_F0 | FD_T4); 3155: } 3156: 3157: objledata(seg,offset,val,lcfd,framedatum,idx); 3158: } 3159: 3160: /******************************* 3161: * Refer to an identifier. 3162: * Input: 3163: * seg = where the address is going (CODE or DATA) 3164: * offset = offset within seg 3165: * s -> Symbol table entry for identifier 3166: * val = displacement from identifier 3167: * flags = CFselfrel: self-relative 3168: * CFseg: get segment 3169: * CFoff: get offset 3170: * Returns: 3171: * number of bytes in reference (2 or 4) 3172: * Example: 3173: * extern int def[]; 3174: * int *abc = &def[3]; 3175: * to allocate storage: 3176: * reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 3177: */ 3178: 3179: int reftoident(int seg,targ_size_t offset,Symbol *s,targ_size_t val, 3180: int flags) 3181: { 3182: unsigned targetdatum; // which datum the symbol is in 3183: unsigned framedatum; 3184: int lc; 3185: int external; // !=0 if identifier is defined externally 3186: int numbytes; 3187: tym_t ty; 3188: 3189: #if 0 3190: printf("reftoident('%s' seg %d, offset x%lx, val x%lx, flags x%x)\n", 3191: s->Sident,seg,offset,val,flags); 3192: printf("Sseg = %d, Sxtrnnum = %d\n",s->Sseg,s->Sxtrnnum); 3193: //symbol_print(s); 3194: #endif 3195: 3196: ty = s->ty(); 3197: while (1) 3198: { 3199: switch (flags & (CFseg | CFoff)) 3200: { case 0: 3201: // Select default 3202: flags |= CFoff; 3203: if (tyfunc(ty)) 3204: { 3205: if (tyfarfunc(ty)) 3206: flags |= CFseg; 3207: } 3208: else // DATA 3209: { 3210: if (LARGEDATA) 3211: flags |= CFseg; 3212: } 3213: continue; 3214: case CFoff: 3215: if (I32) 3216: { 3217: #if 1 3218: if (ty & mTYthread) 3219: { lc = LOC32tlsoffset; 3220: } 3221: else 3222: #endif 3223: lc = obj.LOCoffset; 3224: } 3225: else 3226: { 3227: // The 'loader_resolved' offset is required for VCM 3228: // and Windows support. A fixup of this type is 3229: // relocated by the linker to point to a 'thunk'. 3230: lc = (tyfarfunc(ty) 3231: && !(flags & CFselfrel)) 3232: ? LOCloader_resolved : obj.LOCoffset; 3233: } 3234: numbytes = tysize[TYnptr]; 3235: break; 3236: case CFseg: 3237: lc = LOCbase; 3238: numbytes = 2; 3239: break; 3240: case CFoff | CFseg: 3241: lc = obj.LOCpointer; 3242: numbytes = tysize[TYfptr]; 3243: break; 3244: } 3245: break; 3246: } 3247: 3248: switch (s->Sclass) 3249: { 3250: case SCcomdat: 3251: case_SCcomdat: 3252: case SCextern: 3253: case SCcomdef: 3254: if (s->Sxtrnnum) // identifier is defined somewhere else 3255: { external = s->Sxtrnnum; 3256: #ifdef DEBUG 3257: if (external > obj.extidx) 3258: symbol_print(s); 3259: #endif 3260: assert(external <= obj.extidx); 3261: } 3262: else 3263: { // Don't know yet, worry about it later 3264: Ladd: 3265: addtofixlist(s,offset,seg,val,flags); 3266: return numbytes; 3267: } 3268: break; 3269: case SCinline: 3270: if (config.flags2 & CFG2comdat) 3271: goto case_SCcomdat; // treat as initialized common block 3272: case SCsinline: 3273: case SCstatic: 3274: case SCglobal: 3275: if (s->Sseg == UNKNOWN) 3276: goto Ladd; 3277: if (seg_is_comdat(s->Sseg)) 3278: goto case_SCcomdat; 3279: case SClocstat: 3280: external = 0; // identifier is static or global 3281: // and we know its offset 3282: if (flags & CFoff) 3283: val += s->Soffset; 3284: break; 3285: default: 3286: #ifdef DEBUG 3287: symbol_print(s); 3288: #endif 3289: assert(0); 3290: } 3291: 3292: lc |= (flags & CFselfrel) ? LOCATselfrel : LOCATsegrel; 3293: if (external) 3294: { lc |= FD_T6; 3295: targetdatum = external; 3296: switch (s->Sfl) 3297: { 3298: case FLextern: 3299: if (!(ty & (mTYcs | mTYthread))) 3300: goto L1; 3301: case FLfunc: 3302: case FLfardata: 3303: case FLcsdata: 3304: case FLtlsdata: 3305: if (config.exe & EX_flat) 3306: { lc |= FD_F1; 3307: framedatum = 1; 3308: } 3309: else 3310: { 3311: //case FLtlsdata: 3312: lc |= FD_F2; 3313: framedatum = targetdatum; 3314: } 3315: break; 3316: default: 3317: goto L1; 3318: } 3319: } 3320: else 3321: { 3322: lc |= FD_T4; // target is always a segment 3323: targetdatum = s->Sseg; 3324: assert(targetdatum != UNKNOWN); 3325: switch (s->Sfl) 3326: { 3327: case FLextern: 3328: if (!(ty & (mTYcs | mTYthread))) 3329: goto L1; 3330: case FLfunc: 3331: case FLfardata: 3332: case FLcsdata: 3333: case FLtlsdata: 3334: if (config.exe & EX_flat) 3335: { lc |= FD_F1; 3336: framedatum = 1; 3337: } 3338: else 3339: { 3340: //case FLtlsdata: 3341: lc |= FD_F0; 3342: framedatum = targetdatum; 3343: } 3344: break; 3345: default: 3346: L1: 3347: lc |= FD_F1; 3348: framedatum = DGROUPIDX; 3349: if (flags == CFseg) 3350: { lc = LOCATsegrel | LOCbase | FD_F1 | FD_T5; 3351: targetdatum = DGROUPIDX; 3352: } 3353: #if 0 3354: if (flags & CFseg && config.wflags & WFdsnedgroup) 3355: warerr(WM_ds_ne_dgroup); 3356: #endif 3357: break; 3358: } 3359: } 3360: 3361: objledata(seg,offset,val,lc,framedatum,targetdatum); 3362: return numbytes; 3363: } 3364: 3365: /***************************************** 3366: * Generate far16 thunk. 3367: * Input: 3368: * s Symbol to generate a thunk for 3369: */ 3370: 3371: void obj_far16thunk(Symbol *s) 3372: { 3373: static unsigned char cod32_1[] = 3374: { 3375: 0x55, // PUSH EBP 3376: 0x8B,0xEC, // MOV EBP,ESP 3377: 0x83,0xEC,0x04, // SUB ESP,4 3378: 0x53, // PUSH EBX 3379: 0x57, // PUSH EDI 3380: 0x56, // PUSH ESI 3381: 0x06, // PUSH ES 3382: 0x8C,0xD2, // MOV DX,SS 3383: 0x80,0xE2,0x03, // AND DL,3 3384: 0x80,0xCA,0x07, // OR DL,7 3385: 0x89,0x65,0xFC, // MOV -4[EBP],ESP 3386: 0x8C,0xD0, // MOV AX,SS 3387: 0x66,0x3D, // 0x00,0x00 */ /* CMP AX,seg FLAT:_DATA 3388: }; 3389: static unsigned char cod32_2[] = 3390: { 0x0F,0x85,0x10,0x00,0x00,0x00, // JNE L1 3391: 0x8B,0xC4, // MOV EAX,ESP 3392: 0x66,0x3D,0x00,0x08, // CMP AX,2048 3393: 0x0F,0x83,0x04,0x00,0x00,0x00, // JAE L1 3394: 0x66,0x33,0xC0, // XOR AX,AX 3395: 0x94, // XCHG ESP,EAX 3396: // L1: 3397: 0x55, // PUSH EBP 3398: 0x8B,0xC4, // MOV EAX,ESP 3399: 0x16, // PUSH SS 3400: 0x50, // PUSH EAX 3401: 0x8D,0x75,0x08, // LEA ESI,8[EBP] 3402: 0x81,0xEC,0x00,0x00,0x00,0x00, // SUB ESP,numparam 3403: 0x8B,0xFC, // MOV EDI,ESP 3404: 0xB9,0x00,0x00,0x00,0x00, // MOV ECX,numparam 3405: 0x66,0xF3,0xA4, // REP MOVSB 3406: 0x8B,0xC4, // MOV EAX,ESP 3407: 0xC1,0xC8,0x10, // ROR EAX,16 3408: 0x66,0xC1,0xE0,0x03, // SHL AX,3 3409: 0x0A,0xC2, // OR AL,DL 3410: 0xC1,0xC0,0x10, // ROL EAX,16 3411: 0x50, // PUSH EAX 3412: 0x66,0x0F,0xB2,0x24,0x24, // LSS SP,[ESP] 3413: 0x66,0xEA, // 0,0,0,0, */ /* JMPF L3 3414: }; 3415: static unsigned char cod32_3[] = 3416: { // L2: 3417: 0xC1,0xE0,0x10, // SHL EAX,16 3418: 0x0F,0xAC,0xD0,0x10, // SHRD EAX,EDX,16 3419: 0x0F,0xB7,0xE4, // MOVZX ESP,SP 3420: 0x0F,0xB2,0x24,0x24, // LSS ESP,[ESP] 3421: 0x5D, // POP EBP 3422: 0x8B,0x65,0xFC, // MOV ESP,-4[EBP] 3423: 0x07, // POP ES 3424: 0x5E, // POP ESI 3425: 0x5F, // POP EDI 3426: 0x5B, // POP EBX 3427: 0xC9, // LEAVE 3428: 0xC2,0x00,0x00 // RET numparam 3429: }; 3430: 3431: unsigned numparam = 24; 3432: targ_size_t L2offset; 3433: int idx; 3434: 3435: s->Sclass = SCstatic; 3436: s->Sseg = cseg; // identifier is defined in code segment 3437: s->Soffset = Coffset; 3438: 3439: // Store numparam into right places 3440: assert((numparam & 0xFFFF) == numparam); // 2 byte value 3441: TOWORD(&cod32_2[32],numparam); 3442: TOWORD(&cod32_2[32 + 7],numparam); 3443: TOWORD(&cod32_3[sizeof(cod32_3) - 2],numparam); 3444: 3445: //------------------------------------------ 3446: // Generate CODE16 segment if it isn't there already 3447: if (obj.code16 == 0) 3448: { 3449: // Define CODE16 segment for far16 thunks 3450: 3451: static char lname[] = { "\06CODE16" }; 3452: unsigned attr; 3453: 3454: // Put out LNAMES record 3455: objrecord(LNAMES,lname,sizeof(lname) - 1); 3456: 3457: obj.code16segi = obj_newfarseg(0,4); 3458: obj.code16 = obj.segidx; // code16 segment index 3459: obj.CODE16offset = 0; 3460: 3461: // class CODE 3462: attr = SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16); 3463: SegData[obj.code16segi]->attr = attr; 3464: objsegdef(attr,0,obj.lnameidx++,4); 3465: obj.segidx++; 3466: } 3467: 3468: //------------------------------------------ 3469: // Output the 32 bit thunk 3470: 3471: obj_bytes(cseg,Coffset,sizeof(cod32_1),cod32_1); 3472: Coffset += sizeof(cod32_1); 3473: 3474: // Put out fixup for SEG FLAT:_DATA 3475: objledata(cseg,Coffset,0,LOCATsegrel|LOCbase|FD_F1|FD_T4, 3476: DGROUPIDX,DATA); 3477: Coffset += 2; 3478: 3479: obj_bytes(cseg,Coffset,sizeof(cod32_2),cod32_2); 3480: Coffset += sizeof(cod32_2); 3481: 3482: // Put out fixup to CODE16 part of thunk 3483: objledata(cseg,Coffset,obj.CODE16offset,LOCATsegrel|LOC16pointer|FD_F0|FD_T4, 3484: obj.code16,obj.code16); 3485: Coffset += 4; 3486: 3487: L2offset = Coffset; 3488: obj_bytes(cseg,Coffset,sizeof(cod32_3),cod32_3); 3489: Coffset += sizeof(cod32_3); 3490: 3491: s->Ssize = Coffset - s->Soffset; // size of thunk 3492: 3493: //------------------------------------------ 3494: // Output the 16 bit thunk 3495: 3496: obj_byte(obj.code16,obj.CODE16offset++,0x9A); // CALLF function 3497: 3498: // Make function external 3499: idx = objextern(s); // use Pascal name mangling 3500: 3501: // Output fixup for function 3502: objledata(obj.code16,obj.CODE16offset,0,LOCATsegrel|LOC16pointer|FD_F2|FD_T6, 3503: idx,idx); 3504: obj.CODE16offset += 4; 3505: 3506: obj_bytes(obj.code16,obj.CODE16offset,3,"\x66\x67\xEA"); // JMPF L2 3507: obj.CODE16offset += 3; 3508: 3509: objledata(obj.code16,obj.CODE16offset,L2offset, 3510: LOCATsegrel | LOC32pointer | FD_F1 | FD_T4,DGROUPIDX,cseg); 3511: obj.CODE16offset += 6; 3512: 3513: SegData[obj.code16segi]->SDoffset = obj.CODE16offset; 3514: } 3515: 3516: /************************************** 3517: * Mark object file as using floating point. 3518: */ 3519: 3520: void obj_fltused() 3521: { 3522: if (!obj.fltused) 3523: { 3524: obj.fltused = 1; 3525: if (!(config.flags3 & CFG3wkfloat)) 3526: objextdef("__fltused"); 3527: } 3528: } 3529: 3530: 3531: /**************************************** 3532: * Find longest match of pattern[] in dict[]. 3533: */ 3534: 3535: static int longest_match(char *dict, int dlen, char *pattern, int plen, 3536: int *pmatchoff, int *pmatchlen) 3537: { 3538: int matchlen = 0; 3539: int matchoff; 3540: 3541: int i; 3542: int j; 3543: 3544: for (i = 0; i < dlen; i++) 3545: { 3546: if (dict[i] == pattern[0]) 3547: { 3548: for (j = 1; 1; j++) 3549: { 3550: if (i + j == dlen || j == plen) 3551: break; 3552: if (dict[i + j] != pattern[j]) 3553: break; 3554: } 3555: if (j >= matchlen) 3556: { 3557: matchlen = j; 3558: matchoff = i; 3559: } 3560: } 3561: } 3562: 3563: if (matchlen > 1) 3564: { 3565: *pmatchlen = matchlen; 3566: *pmatchoff = matchoff; 3567: return 1; // found a match 3568: } 3569: return 0; // no match 3570: } 3571: 3572: /****************************************** 3573: * Compress an identifier. 3574: * Format: if ASCII, then it's just the char 3575: * if high bit set, then it's a length/offset pair 3576: * Returns: 3577: * malloc'd compressed identifier 3578: */ 3579: 3580: char *id_compress(char *id, int idlen) 3581: { 3582: int i; 3583: int count = 0; 3584: char *p; 3585: 3586: p = (char *)malloc(idlen + 1); 3587: for (i = 0; i < idlen; i++) 3588: { 3589: int matchoff; 3590: int matchlen; 3591: 3592: int j = 0; 3593: if (i > 1023) 3594: j = i - 1023; 3595: 3596: if (longest_match(id + j, i - j, id + i, idlen - i, &matchoff, &matchlen)) 3597: { int off; 3598: 3599: matchoff += j; 3600: off = i - matchoff; 3601: //printf("matchoff = %3d, matchlen = %2d, off = %d\n", matchoff, matchlen, off); 3602: assert(off >= matchlen); 3603: 3604: if (off <= 8 && matchlen <= 8) 3605: { 3606: p[count] = 0xC0 | ((off - 1) << 3) | (matchlen - 1); 3607: count++; 3608: i += matchlen - 1; 3609: continue; 3610: } 3611: else if (matchlen > 2 && off < 1024) 3612: { 3613: if (matchlen >= 1024) 3614: matchlen = 1023; // longest representable match 3615: p[count + 0] = 0x80 | ((matchlen >> 4) & 0x38) | ((off >> 7) & 7);
warning C6011: Dereferencing NULL pointer 'p': Lines: 3582, 3583, 3584, 3586, 3587, 3589, 3590, 3592, 3593, 3596, 3597, 3599, 3600, 3602, 3604, 3611, 3613, 3615
3616: p[count + 1] = 0x80 | matchlen; 3617: p[count + 2] = 0x80 | off;
warning C6386: Buffer overrun: accessing 'p', the writable size is 'idlen+1' bytes, but '3' bytes might be written: Lines: 3582, 3583, 3584, 3586, 3587, 3589, 3590, 3592, 3593, 3596, 3597, 3599, 3600, 3602, 3604, 3611, 3613, 3615, 3616, 3617
3618: count += 3; 3619: i += matchlen - 1; 3620: continue; 3621: } 3622: } 3623: p[count] = id[i]; 3624: count++; 3625: } 3626: p[count] = 0; 3627: //printf("old size = %d, new size = %d\n", idlen, count); 3628: return p; 3629: } 3630: 3631: #endif 3632: #endif 3633: