Mercurial > projects > ddmd
annotate dmd/Library.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | e7769d53e750 |
children | 190ba98276b3 |
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; | |
178 | 133 |
0 | 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; | |
178 | 151 |
0 | 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 */ | |
178 | 161 |
0 | 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 | |
178 | 257 import dmd.TObject; |
258 | |
259 class Library : TObject | |
0 | 260 { |
261 File libfile; | |
262 Array objmodules; // ObjModule[] | |
263 Array objsymbols; // ObjSymbol[] | |
264 | |
265 StringTable tab; | |
266 | |
267 this() | |
268 { | |
178 | 269 register(); |
0 | 270 libfile = null; |
178 | 271 |
0 | 272 objmodules = new Array(); |
273 objsymbols = new Array(); | |
274 } | |
275 | |
276 /*********************************** | |
277 * Set the library file name based on the output directory | |
278 * and the filename. | |
279 * Add default library file name extension. | |
280 */ | |
281 void setFilename(string dir, string filename) | |
282 { | |
283 string arg = filename; | |
284 if (arg.length == 0) | |
178 | 285 { |
0 | 286 // Generate lib file name from first obj name |
287 string n = (cast(String)global.params.objfiles.data[0]).str; | |
288 | |
289 n = FileName.name(n); | |
290 FileName fn = FileName.forceExt(n, global.lib_ext); | |
291 arg = fn.toChars(); | |
292 } | |
293 if (!FileName.absolute(arg)) | |
294 arg = FileName.combine(dir, arg); | |
295 | |
296 FileName libfilename = FileName.defaultExt(arg, global.lib_ext); | |
297 libfile = new File(libfilename); | |
298 } | |
299 | |
300 /*************************************** | |
301 * Add object module or library to the library. | |
302 * Examine the buffer to see which it is. | |
303 * If the buffer is null, use module_name as the file name | |
304 * and load the file. | |
305 */ | |
306 void addObject(string module_name, void *buf, size_t buflen) | |
307 { | |
308 version (LOG) { | |
309 printf("Library.addObject(%s)\n", module_name ? module_name : ""); | |
310 } | |
311 if (!buf) | |
312 { | |
313 assert(module_name); | |
314 scope FileName f = new FileName(module_name); | |
315 scope File file = new File(f); | |
316 file.readv(); | |
317 buf = file.buffer; | |
318 buflen = file.len; | |
319 file.ref_ = 1; | |
320 } | |
321 | |
322 uint g_page_size; | |
323 ubyte* pstart = cast(ubyte*)buf; | |
324 int islibrary = 0; | |
325 | |
326 /* See if it's an OMF library. | |
327 * Don't go by file extension. | |
328 */ | |
329 | |
330 /* Determine if it is an OMF library, an OMF object module, | |
331 * or something else. | |
332 */ | |
333 if (buflen < LibHeader.sizeof) | |
334 { | |
335 Lcorrupt: | |
336 error("corrupt object module"); | |
337 } | |
338 LibHeader* lh = cast(LibHeader*)buf; | |
339 if (lh.recTyp == 0xF0) | |
340 { /* OMF library | |
341 * The modules are all at buf[g_page_size .. lh.lSymSeek] | |
342 */ | |
343 islibrary = 1; | |
344 g_page_size = lh.pagesize + 3; | |
345 buf = cast(void*)(pstart + g_page_size); | |
346 if (lh.lSymSeek > buflen || | |
347 g_page_size > buflen) | |
348 goto Lcorrupt; | |
349 buflen = lh.lSymSeek - g_page_size; | |
350 } | |
351 else if (lh.recTyp == '!' && memcmp(lh, "!<arch>\n".ptr, 8) == 0) | |
352 { | |
353 error("COFF libraries not supported"); | |
354 return; | |
355 } | |
356 else | |
178 | 357 { |
0 | 358 // Not a library, assume OMF object module |
359 g_page_size = 16; | |
360 } | |
361 | |
362 /* Split up the buffer buf[0..buflen] into multiple object modules, | |
363 * each aligned on a g_page_size boundary. | |
364 */ | |
365 | |
366 ObjModule* om = null; | |
367 int first_module = 1; | |
368 | |
369 ubyte* p = cast(ubyte*)buf; | |
370 ubyte* pend = p + buflen; | |
371 ubyte* pnext; | |
372 for (; p < pend; p = pnext) // for each OMF record | |
373 { | |
374 if (p + 3 >= pend) | |
375 goto Lcorrupt; | |
376 ubyte recTyp = *p; | |
377 ushort recLen = *cast(ushort*)(p + 1); | |
378 pnext = p + 3 + recLen; | |
379 if (pnext > pend) | |
380 goto Lcorrupt; | |
381 recLen--; /* forget the checksum */ | |
382 | |
383 switch (recTyp) | |
384 { | |
385 case LHEADR : | |
386 case THEADR : | |
387 if (!om) | |
178 | 388 { |
0 | 389 char name[LIBIDMAX + 1]; |
390 om = new ObjModule(); | |
391 om.flags = 0; | |
392 om.base = p; | |
393 p += 3; | |
394 parseName(&p, name.ptr); | |
395 if (first_module && module_name && !islibrary) | |
178 | 396 { |
0 | 397 // Remove path and extension |
398 string fname = FileName.name(module_name); | |
399 string ext = FileName.ext(fname); | |
400 if (ext.length != 0) { | |
401 fname = fname[0..$-ext.length-1]; | |
402 } | |
403 | |
404 om.name = fname; | |
405 } | |
406 else | |
178 | 407 { |
0 | 408 /* Use THEADR name as module name, |
409 * removing path and extension. | |
410 */ | |
411 string fname = FileName.name(fromStringz(name.ptr)); | |
412 string ext = FileName.ext(fname); | |
413 if (ext.length != 0) { | |
414 fname = fname[0..$-ext.length-1]; | |
415 } | |
178 | 416 |
0 | 417 om.name = fname; |
418 om.flags |= MFtheadr; | |
419 } | |
420 if (strcmp(name.ptr, "C".ptr) == 0) // old C compilers did this | |
178 | 421 { |
0 | 422 om.flags |= MFgentheadr; // generate our own THEADR |
423 om.base = pnext; // skip past THEADR | |
424 } | |
425 objmodules.push(cast(void*)om); | |
426 first_module = 0; | |
427 } | |
428 break; | |
429 | |
430 case MODEND : | |
431 case M386END: | |
432 if (om) | |
178 | 433 { |
0 | 434 om.page = cast(ushort)((om.base - pstart) / g_page_size); |
435 om.length = pnext - om.base; | |
436 om = null; | |
437 } | |
438 // Round up to next page | |
439 uint t = pnext - pstart; | |
440 t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1); | |
441 pnext = pstart + t; | |
442 break; | |
178 | 443 |
0 | 444 default: |
178 | 445 // ignore |
0 | 446 ; |
447 } | |
448 } | |
449 | |
450 if (om) | |
451 goto Lcorrupt; // missing MODEND record | |
452 } | |
453 | |
454 void addLibrary(void *buf, size_t buflen) | |
455 { | |
456 assert(false); | |
457 } | |
458 | |
459 void write() | |
460 { | |
461 if (global.params.verbose) | |
462 writef("library %s\n", libfile.name.toChars()); | |
463 | |
464 scope OutBuffer libbuf = new OutBuffer(); | |
465 WriteLibToBuffer(libbuf); | |
466 | |
467 // Transfer image to file | |
468 libfile.setbuffer(libbuf.data, libbuf.offset); | |
469 libbuf.extractData(); | |
470 | |
471 string p = FileName.path(libfile.name.toChars()); | |
472 FileName.ensurePathExists(p); | |
473 | |
474 libfile.writev(); | |
475 } | |
476 | |
477 private: | |
478 void addSymbol(ObjModule* om, string name, int pickAny = 0) | |
479 { | |
480 version (LOG) { | |
481 printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny); | |
482 } | |
178 | 483 Object* s = tab.insert(name); |
0 | 484 if (!s) |
178 | 485 { |
0 | 486 // already in table |
487 if (!pickAny) | |
178 | 488 { |
0 | 489 s = tab.lookup(name); |
490 assert(s); | |
178 | 491 ObjSymbol* os = *cast(ObjSymbol**)s; |
0 | 492 error("multiple definition of %s: %s and %s: %s", |
493 om.name, name, os.om.name, os.name); | |
494 } | |
495 } | |
496 else | |
497 { | |
498 ObjSymbol* os = new ObjSymbol(); | |
499 os.name = name; | |
500 os.om = om; | |
178 | 501 *s = cast(Object)cast(void*)os; /// !!!! |
0 | 502 |
503 objsymbols.push(os); | |
504 } | |
505 } | |
178 | 506 |
0 | 507 void scanObjModule(ObjModule* om) |
508 { | |
509 int easyomf; | |
510 uint u; | |
511 ubyte result = 0; | |
512 char name[LIBIDMAX + 1]; | |
513 | |
514 scope Array names = new Array(); | |
515 names.push(null); // don't use index 0 | |
516 | |
517 assert(om); | |
518 easyomf = 0; // assume not EASY-OMF | |
519 ubyte* pend = om.base + om.length; | |
520 | |
521 ubyte* pnext; | |
522 for (ubyte* p = om.base; 1; p = pnext) | |
523 { | |
524 assert(p < pend); | |
525 ubyte recTyp = *p++; | |
526 ushort recLen = *cast(ushort*)p; | |
527 p += 2; | |
528 pnext = p + recLen; | |
529 recLen--; // forget the checksum | |
530 | |
531 switch (recTyp) | |
532 { | |
533 case LNAMES: | |
534 case LLNAMES: | |
535 while (p + 1 < pnext) | |
536 { | |
537 uint len = parseName(&p, name.ptr); | |
538 names.push(cast(void*)new String(name[0..len].idup)); | |
539 } | |
540 break; | |
541 | |
542 case PUBDEF: | |
543 if (easyomf) | |
544 recTyp = PUB386; // convert to MS format | |
545 case PUB386: | |
546 if (!(parseIdx(&p) | parseIdx(&p))) | |
547 p += 2; // skip seg, grp, frame | |
548 while (p + 1 < pnext) | |
549 { | |
550 uint len = parseName(&p, name.ptr); | |
551 p += (recTyp == PUBDEF) ? 2 : 4; // skip offset | |
552 parseIdx(&p); // skip type index | |
553 addSymbol(om, name[0..len].idup); | |
554 } | |
555 break; | |
556 | |
557 case COMDAT: | |
558 if (easyomf) | |
559 recTyp = COMDAT+1; // convert to MS format | |
560 case COMDAT+1: | |
561 int pickAny = 0; | |
562 | |
563 if (*p++ & 5) // if continuation or local comdat | |
564 break; | |
565 | |
566 ubyte attr = *p++; | |
567 if (attr & 0xF0) // attr: if multiple instances allowed | |
568 pickAny = 1; | |
569 p++; // align | |
570 | |
571 p += 2; // enum data offset | |
572 if (recTyp == COMDAT+1) | |
573 p += 2; // enum data offset | |
574 | |
575 parseIdx(&p); // type index | |
576 | |
577 if ((attr & 0x0F) == 0) // if explicit allocation | |
578 { parseIdx(&p); // base group | |
579 parseIdx(&p); // base segment | |
580 } | |
581 | |
582 uint idx = parseIdx(&p); // public name index | |
583 if( idx == 0 || idx >= names.dim) | |
584 { | |
585 //debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames)); | |
586 error("corrupt COMDAT"); | |
587 return; | |
588 } | |
589 | |
590 //printf("[s] name='%s'\n",name); | |
591 addSymbol(om, (cast(String)names.data[idx]).str, pickAny); | |
592 break; | |
593 | |
594 case ALIAS: | |
595 while (p + 1 < pnext) | |
596 { | |
597 uint len = parseName(&p, name.ptr); | |
598 addSymbol(om, name[0..len].idup); | |
599 parseName(&p, name.ptr); | |
600 } | |
601 break; | |
602 | |
603 case MODEND: | |
604 case M386END: | |
605 result = 1; | |
606 goto Ret; | |
607 | |
608 case COMENT: | |
609 // Recognize Phar Lap EASY-OMF format | |
178 | 610 { |
169 | 611 enum ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6']; |
0 | 612 |
613 if (recLen == omfstr.sizeof) | |
614 { | |
615 for (uint i = 0; i < omfstr.sizeof; i++) | |
616 if (*p++ != omfstr[i]) | |
617 goto L1; | |
618 easyomf = 1; | |
619 break; | |
620 L1: ; | |
621 } | |
622 } | |
623 // Recognize .IMPDEF Import Definition Records | |
178 | 624 { |
169 | 625 enum ubyte[3] omfstr = [0, 0xA0, 1]; |
0 | 626 |
627 if (recLen >= 7) | |
628 { | |
629 p++; | |
630 for (uint i = 1; i < omfstr.sizeof; i++) | |
631 if (*p++ != omfstr[i]) | |
632 goto L2; | |
633 p++; // skip OrdFlag field | |
634 uint len = parseName(&p, name.ptr); | |
635 addSymbol(om, name[0..len].idup); | |
636 break; | |
637 L2: ; | |
638 } | |
639 } | |
640 break; | |
641 | |
642 default: | |
178 | 643 // ignore |
0 | 644 ; |
645 } | |
646 } | |
647 | |
648 Ret: | |
649 ; | |
650 ///for (u = 1; u < names.dim; u++) | |
651 /// free(names.data[u]); | |
652 } | |
178 | 653 |
0 | 654 /*********************************** |
655 * Calculates number of pages needed for dictionary | |
656 * Returns: | |
657 * number of pages | |
658 */ | |
659 ushort numDictPages(uint padding) | |
660 { | |
661 ushort ndicpages; | |
662 ushort bucksForHash; | |
663 ushort bucksForSize; | |
664 uint symSize = 0; | |
665 | |
666 for (int i = 0; i < objsymbols.dim; i++) | |
178 | 667 { |
0 | 668 ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i]; |
669 symSize += ( s.name.length + 4 ) & ~1; | |
670 } | |
671 | |
672 for (int i = 0; i < objmodules.dim; i++) | |
178 | 673 { |
0 | 674 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
675 | |
676 size_t len = om.name.length; | |
677 if (len > 0xFF) | |
678 len += 2; // Digital Mars long name extension | |
679 symSize += ( len + 4 + 1 ) & ~1; | |
680 } | |
681 | |
682 bucksForHash = cast(ushort)((objsymbols.dim + objmodules.dim + HASHMOD - 3) / (HASHMOD - 2)); | |
683 bucksForSize = cast(ushort)((symSize + BUCKETSIZE - padding - padding - 1) / (BUCKETSIZE - padding)); | |
684 | |
685 ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize; | |
686 //printf("ndicpages = %u\n",ndicpages); | |
687 | |
688 // Find prime number greater than ndicpages | |
169 | 689 enum uint[] primes = |
0 | 690 [ 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43, |
691 47,53,59,61,67,71,73,79,83,89,97,101,103, | |
692 107,109,113,127,131,137,139,149,151,157, | |
693 163,167,173,179,181,191,193,197,199,211, | |
694 223,227,229,233,239,241,251,257,263,269, | |
695 271,277,281,283,293,307,311,313,317,331, | |
696 337,347,349,353,359,367,373,379,383,389, | |
697 397,401,409,419,421,431,433,439,443,449, | |
698 457,461,463,467,479,487,491,499,503,509, | |
699 //521,523,541,547, | |
700 0 | |
701 ]; | |
702 | |
703 for (int i = 0; 1; i++) | |
704 { | |
705 if ( primes[i] == 0 ) | |
178 | 706 { |
0 | 707 // Quick and easy way is out. |
708 // Now try and find first prime number > ndicpages | |
709 uint prime; | |
710 | |
711 for (prime = (ndicpages + 1) | 1; 1; prime += 2) | |
712 { // Determine if prime is prime | |
713 for (uint u = 3; u < prime / 2; u += 2) | |
714 { | |
715 if ((prime / u) * u == prime) | |
716 goto L1; | |
717 } | |
718 break; | |
719 | |
720 L1: ; | |
721 } | |
722 ndicpages = cast(ushort)prime; | |
723 break; | |
724 } | |
725 | |
726 if (primes[i] > ndicpages) | |
727 { | |
728 ndicpages = cast(ushort)primes[i]; | |
729 break; | |
730 } | |
731 } | |
732 | |
733 return ndicpages; | |
734 } | |
178 | 735 |
0 | 736 /******************************************* |
737 * Write the module and symbol names to the dictionary. | |
738 * Returns: | |
739 * 0 failure | |
740 */ | |
741 int FillDict(ubyte* bucketsP, ushort ndicpages) | |
742 { | |
743 ubyte entry[4 + LIBIDMAX + 2 + 1]; | |
744 | |
745 //printf("FillDict()\n"); | |
746 | |
747 // Add each of the module names | |
748 for (int i = 0; i < objmodules.dim; i++) | |
178 | 749 { |
0 | 750 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
751 | |
752 ushort n = cast(ushort)om.name.length; | |
753 if (n > 255) | |
178 | 754 { |
0 | 755 entry[0] = 0xFF; |
756 entry[1] = 0; | |
757 *cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1); | |
758 memcpy(entry.ptr + 4, om.name.ptr, n); | |
759 n += 3; | |
760 } | |
761 else | |
178 | 762 { |
0 | 763 entry[ 0 ] = cast(ubyte)(1 + n); |
764 memcpy(entry.ptr + 1, om.name.ptr, n ); | |
765 } | |
766 entry[ n + 1 ] = '!'; | |
767 *(cast(ushort*)( n + 2 + entry.ptr )) = om.page; | |
768 if ( n & 1 ) | |
769 entry[ n + 2 + 2 ] = 0; | |
770 if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n + 1 ) ) | |
771 return 0; | |
772 } | |
773 | |
774 // Sort the symbols | |
775 qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare ); | |
776 | |
777 // Add each of the symbols | |
778 for (int i = 0; i < objsymbols.dim; i++) | |
178 | 779 { |
0 | 780 ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i]; |
781 | |
782 ushort n = cast(ushort)os.name.length; | |
783 if (n > 255) | |
178 | 784 { |
0 | 785 entry[0] = 0xFF; |
786 entry[1] = 0; | |
787 *cast(ushort*)(entry.ptr + 2) = n; | |
788 memcpy(entry.ptr + 4, os.name.ptr, n); | |
789 n += 3; | |
790 } | |
791 else | |
178 | 792 { |
0 | 793 entry[ 0 ] = cast(ubyte)n; |
794 memcpy( entry.ptr + 1, os.name.ptr, n ); | |
795 } | |
796 *(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page; | |
797 if ( (n & 1) == 0 ) | |
798 entry[ n + 3] = 0; | |
799 if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n ) ) | |
800 { | |
801 return 0; | |
802 } | |
803 } | |
804 | |
805 return 1; | |
806 } | |
178 | 807 |
0 | 808 /********************************************** |
809 * Create and write library to libbuf. | |
810 * The library consists of: | |
811 * library header | |
812 * object modules... | |
813 * dictionary header | |
814 * dictionary pages... | |
815 */ | |
816 void WriteLibToBuffer(OutBuffer libbuf) | |
817 { | |
818 /* Scan each of the object modules for symbols | |
819 * to go into the dictionary | |
820 */ | |
821 for (int i = 0; i < objmodules.dim; i++) | |
178 | 822 { |
0 | 823 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
824 scanObjModule(om); | |
825 } | |
826 | |
827 uint g_page_size = 16; | |
828 | |
829 /* Calculate page size so that the number of pages | |
830 * fits in 16 bits. This is because object modules | |
831 * are indexed by page number, stored as an unsigned short. | |
832 */ | |
833 while (1) | |
834 { | |
835 Lagain: | |
836 version (LOG) { | |
837 printf("g_page_size = %d\n", g_page_size); | |
838 } | |
839 uint offset = g_page_size; | |
840 | |
841 for (int i = 0; i < objmodules.dim; i++) | |
178 | 842 { |
0 | 843 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
844 | |
845 uint page = offset / g_page_size; | |
846 if (page > 0xFFFF) | |
847 { | |
848 // Page size is too small, double it and try again | |
849 g_page_size *= 2; | |
850 goto Lagain; | |
851 } | |
852 | |
853 // Write out the object module m | |
854 if (om.flags & MFgentheadr) // if generate THEADR record | |
855 { | |
856 size_t size = om.name.length; | |
857 assert(size <= LIBIDMAX); | |
858 | |
859 offset += size + 5; | |
860 //offset += om.length - (size + 5); | |
861 offset += om.length; | |
862 } | |
863 else | |
864 offset += om.length; | |
865 | |
866 // Round the size of the file up to the next page size | |
867 // by filling with 0s | |
868 uint n = (g_page_size - 1) & offset; | |
869 if (n) | |
870 offset += g_page_size - n; | |
871 } | |
872 break; | |
873 } | |
874 | |
875 | |
876 /* Leave one page of 0s at start as a dummy library header. | |
877 * Fill it in later with the real data. | |
878 */ | |
879 libbuf.fill0(g_page_size); | |
880 | |
881 /* Write each object module into the library | |
882 */ | |
883 for (int i = 0; i < objmodules.dim; i++) | |
178 | 884 { |
0 | 885 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
886 | |
887 uint page = libbuf.offset / g_page_size; | |
888 assert(page <= 0xFFFF); | |
889 om.page = cast(ushort)page; | |
890 | |
891 // Write out the object module om | |
892 if (om.flags & MFgentheadr) // if generate THEADR record | |
893 { | |
894 uint size = om.name.length; | |
895 ubyte header[4 + LIBIDMAX + 1]; | |
896 | |
897 header [0] = THEADR; | |
898 header [1] = cast(ubyte)(2 + size); | |
899 header [2] = 0; | |
900 header [3] = cast(ubyte)size; | |
901 assert(size <= 0xFF - 2); | |
902 | |
903 memcpy(4 + header.ptr, om.name.ptr, size); | |
904 | |
905 // Compute and store record checksum | |
906 uint n = size + 4; | |
907 ubyte checksum = 0; | |
908 ubyte* p = header.ptr; | |
909 while (n--) | |
178 | 910 { |
0 | 911 checksum -= *p; |
912 p++; | |
913 } | |
914 *p = checksum; | |
915 | |
916 libbuf.write(header.ptr, size + 5); | |
917 //libbuf.write(om.base, om.length - (size + 5)); | |
918 libbuf.write(om.base, om.length); | |
919 } | |
920 else | |
921 libbuf.write(om.base, om.length); | |
922 | |
923 // Round the size of the file up to the next page size | |
924 // by filling with 0s | |
925 uint n = (g_page_size - 1) & libbuf.offset; | |
926 if (n) | |
927 libbuf.fill0(g_page_size - n); | |
928 } | |
929 | |
930 // File offset of start of dictionary | |
931 uint offset = libbuf.offset; | |
932 | |
933 // Write dictionary header, then round it to a BUCKETPAGE boundary | |
934 ushort size = (BUCKETPAGE - (cast(short)offset + 3)) & (BUCKETPAGE - 1); | |
935 libbuf.writeByte(0xF1); | |
936 libbuf.writeword(size); | |
937 libbuf.fill0(size); | |
938 | |
939 // Create dictionary | |
940 ubyte* bucketsP = null; | |
941 ushort ndicpages; | |
942 ushort padding = 32; | |
943 for (;;) | |
944 { | |
945 ndicpages = numDictPages(padding); | |
946 | |
947 version (LOG) { | |
948 printf("ndicpages = %d\n", ndicpages); | |
949 } | |
950 // Allocate dictionary | |
951 if (bucketsP) | |
2 | 952 bucketsP = cast(ubyte*)GC.realloc(bucketsP, ndicpages * BUCKETPAGE); |
0 | 953 else |
2 | 954 bucketsP = cast(ubyte*)GC.malloc(ndicpages * BUCKETPAGE); |
0 | 955 assert(bucketsP); |
956 memset(bucketsP, 0, ndicpages * BUCKETPAGE); | |
957 for (uint u = 0; u < ndicpages; u++) | |
958 { | |
959 // 'next available' slot | |
960 bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; | |
961 } | |
962 | |
178 | 963 if (FillDict(bucketsP, ndicpages)) |
0 | 964 break; |
965 padding += 16; // try again with more margins | |
966 } | |
967 | |
968 // Write dictionary | |
969 libbuf.write(bucketsP, ndicpages * BUCKETPAGE); | |
2 | 970 ///if (bucketsP) |
971 /// free(bucketsP); | |
0 | 972 |
973 // Create library header | |
974 Libheader libHeader; | |
975 memset(&libHeader, 0, Libheader.sizeof); | |
976 libHeader.recTyp = 0xF0; | |
977 libHeader.recLen = 0x0D; | |
978 libHeader.trailerPosn = offset + (3 + size); | |
979 libHeader.recLen = cast(ushort)(g_page_size - 3); | |
980 libHeader.ndicpages = ndicpages; | |
981 libHeader.flags = 1; // always case sensitive | |
982 | |
983 // Write library header at start of buffer | |
984 memcpy(libbuf.data, &libHeader, libHeader.sizeof); | |
985 } | |
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
|
986 } |
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 } // 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
|
988 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
|
989 { |
178 | 990 |
991 import dmd.TObject; | |
992 | |
993 class Library : TObject | |
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
|
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 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
|
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 } |
178 | 999 |
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
|
1000 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
|
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 } |
178 | 1004 |
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
|
1005 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
|
1006 { |
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
|
1007 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
|
1008 } |
178 | 1009 |
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
|
1010 } |
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
|
1011 } |