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: