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