comparison src/codeview/parser.d @ 1:4a9dcbd9e54f

-files of 0.13 beta -fixes so that it now compiles with the current dmd version
author marton@basel.hu
date Tue, 05 Apr 2011 20:44:01 +0200
parents
children
comparison
equal deleted inserted replaced
0:586e4a649642 1:4a9dcbd9e54f
1 /* Ddbg - Win32 Debugger for the D programming language
2 * Copyright (c) 2007 Jascha Wetzel
3 * All rights reserved. See LICENSE.TXT for details.
4 */
5
6 module codeview.parser;
7
8 import codeview.codeview;
9 import codeview.decl;
10 import codeview.coff;
11
12 import util;
13 import container;
14
15 import std.demangle;
16 import std.string;
17
18 class CodeViewException : Exception
19 {
20 this(string msg) { super(msg); }
21 }
22
23 class CodeViewParser
24 {
25 const uint cv_nb09_sig = intFromStr("NB09");
26
27 static:
28 /**********************************************************************************************
29 Parses the given CodeView section data from the given COFF image.
30 **********************************************************************************************/
31 CodeView parse(COFFImage img, ubyte[] data)
32 {
33 if ( data.length <= 0 )
34 return null;
35 CodeView cv = new CodeView;
36
37 cv.image = img;
38 cv.global_pub = new SymbolSet;
39 cv.global_sym = new SymbolSet;
40 cv.static_sym = new SymbolSet;
41
42 DataReader dr = new DataReader(data);
43 uint sig;
44 dr.read(sig);
45 if ( sig != cv_nb09_sig ) {
46 char[4] sigstr;
47 sigstr[] = (cast(char*)&sig)[0..4];
48 debug DbgIO.println("Unsupported CodeView version %s", sigstr);
49 return null;
50 }
51
52 uint lfoDir;
53 dr.read(lfoDir);
54 dr.seek(lfoDir);
55
56 ubyte[] buf;
57 dr.readA(buf, DirHeader.sizeof);
58 DirHeader* head = cast(DirHeader*)buf.ptr;
59 assert(head.cbDirHeader==DirHeader.sizeof);
60 assert(head.cbDirEntry==DirEntry.sizeof);
61
62 DirEntry[] entries;
63 dr.readA(entries, head.cDir);
64
65 foreach ( DirEntry entry; entries )
66 {
67 ubyte[] section_data;
68 dr.seek(entry.lfo);
69 dr.readA(section_data, entry.cb);
70
71 switch ( entry.subsection )
72 {
73 case sstModule:
74 Module mod = parseModule(cv, section_data);
75 assert ( entry.iMod-1 == cv.modulesByIndex.length );
76 cv.modulesByIndex ~= mod;
77 cv.modulesByName[mod.name] = mod;
78 debug(cvsections) DbgIO.println("sstModule section \"%s\"", mod.name);
79 break;
80 case sstAlignSym:
81 debug(cvsections) DbgIO.println("sstAlignSym section");
82 assert ( entry.iMod <= cv.modulesByIndex.length );
83 Module mod = cv.modulesByIndex[entry.iMod-1];
84 parseSymbols(cv, section_data, mod.symbols, true, mod);
85 break;
86 case sstSrcModule:
87 debug(cvsections) DbgIO.println("sstSrcModule section");
88 assert( entry.iMod <= cv.modulesByIndex.length );
89 parseSrcModule(cv, section_data, cv.modulesByIndex[entry.iMod-1]);
90 break;
91 case sstLibraries:
92 debug(cvsections) DbgIO.println("sstLibraries section");
93 parseLibraries(cv, section_data);
94 break;
95 case sstGlobalSym:
96 debug(cvsections) DbgIO.println("sstGlobalSym section");
97 parsePackedSymbols(cv, section_data, cv.global_sym);
98 break;
99 case sstGlobalPub:
100 debug(cvsections) DbgIO.println("sstGlobalPub section");
101 parsePackedSymbols(cv, section_data, cv.global_pub);
102 break;
103 case sstStaticSym:
104 debug(cvsections) DbgIO.println("sstStaticSym section");
105 parsePackedSymbols(cv, section_data, cv.static_sym);
106 break;
107 case sstGlobalTypes:
108 debug(cvsections) DbgIO.println("sstGlobalTypes section");
109 parseGlobalTypes(cv, section_data, entry.lfo);
110 break;
111 case sstSegMap:
112 debug(cvsections) DbgIO.println("sstSegMap section");
113 break;
114 case sstSegName:
115 debug(cvsections) DbgIO.println("sstSegName section");
116 break;
117 case sstFileIndex:
118 debug(cvsections) DbgIO.println("sstFileIndex section");
119 break;
120 case sstSymbols:
121 case sstTypes:
122 case sstPublic:
123 case sstPublicSym:
124 case sstSrcLnSeg:
125 case sstMPC:
126 case sstPreComp:
127 case sstPreCompMap:
128 case sstOffsetMap16:
129 case sstOffsetMap32:
130 debug DbgIO.println("Unprocessed CV section 0x%x", entry.subsection);
131 break;
132 default:
133 debug DbgIO.println("Unknown CV section 0x%x", entry.subsection);
134 }
135 }
136
137 updateSymbols(cv, cv.global_pub.named_symbols);
138 updateSymbols(cv, cv.global_sym.named_symbols);
139 updateSymbols(cv, cv.static_sym.named_symbols);
140 foreach ( m; cv.modulesByIndex )
141 updateSymbols(cv, m.symbols.named_symbols);
142
143 cv.globalNamedSymbols = new AVLTree!(NamedSymbol);
144 foreach ( ns; cv.global_sym.named_symbols )
145 cv.globalNamedSymbols.insert(ns);
146 foreach ( ns; cv.global_pub.named_symbols )
147 cv.globalNamedSymbols.insert(ns);
148 foreach ( ns; cv.static_sym.named_symbols )
149 cv.globalNamedSymbols.insert(ns);
150
151 cv.updateCodeblocks();
152
153 return cv;
154 }
155
156 private:
157 T min(T)(T a, T b)
158 {
159 return a<b?a:b;
160 }
161
162 /**********************************************************************************************
163 Parse a Module from the given data.
164 **********************************************************************************************/
165 Module parseModule(CodeView cv, ubyte[] data)
166 {
167 if ( data.length <= 0 )
168 throw new CodeViewException("parseModule on empty data");
169 DataReader dr = new DataReader(data);
170 Module mod = new Module(cv);
171 ubyte[] buf;
172 dr.readA(buf, ModuleHeader.sizeof);
173 mod.header = cast(ModuleHeader*)buf.ptr;
174 assert(mod.header.Style==intFromStr("CV"));
175 dr.readA!(SegInfo)(mod.seginfos, mod.header.cSeg);
176 dr.read(mod.name);
177 return mod;
178 }
179
180 /**********************************************************************************************
181
182 **********************************************************************************************/
183 void parseSymbols(CodeView cv, ubyte[] data, SymbolSet symbols, bool skip_to_ssearch=false, Module mod=null)
184 {
185 if ( data.length <= 0 )
186 throw new CodeViewException("parseSymbols on empty data");
187 DataReader dr = new DataReader(data);
188
189 uint num_sym;
190
191 // skip until S_SSEARCH symbol is found
192 while ( skip_to_ssearch && dr.available )
193 {
194 ushort length, index;
195 dr.read(length);
196 dr.read(index);
197 if ( index == SymbolIndex.S_SSEARCH ) {
198 dr.relseek(-4);
199 break;
200 }
201 }
202
203 uint sym_off;
204 bool expecting_arguments=false;
205 ScopeSymbol[uint] scope_syms;
206 ScopeSymbol parent_scope;
207
208 while ( dr.available )
209 {
210 ushort length, index;
211 uint next_symbol, symbol_start;
212
213 void addSymbol(Symbol sym)
214 {
215 assert( !expecting_arguments || parent_scope !is null );
216 if ( parent_scope !is null )
217 {
218 if ( expecting_arguments )
219 (cast(ProcedureSymbol)parent_scope).arguments.add(sym);
220 else
221 parent_scope.symbols.add(sym);
222 }
223 else
224 symbols.add(sym);
225 }
226
227 symbol_start = dr.cursor;
228 dr.read(length);
229 next_symbol = dr.cursor+length;
230 if ( next_symbol > dr.data.length ) {
231 debug DbgIO.println("WARNING: length %d for symbol exceeds block size %d - skipping section", length, dr.data.length);
232 if ( mod !is null )
233 debug DbgIO.println("in module %s", mod.name);
234 return;
235 }
236 dr.read(index);
237
238 ubyte[] buf;
239 switch ( index )
240 {
241 case SymbolIndex.S_COMPILE:
242 ubyte machine,
243 language;
244 ushort flags;
245 dr.read(machine);
246 dr.read(language);
247 dr.read(flags);
248 string version_string;
249 dr.read(version_string);
250 debug(cvsymbols) DbgIO.println("machine: 0x%x, language: %d, flags: 0x%x, version: %s", machine, language, flags, version_string);
251 break;
252 case SymbolIndex.S_SSEARCH:
253 dr.read(sym_off);
254 ushort pe_section;
255 dr.read(pe_section);
256 if ( mod !is null )
257 mod.pe_section = pe_section;
258 break;
259 case SymbolIndex.S_END:
260 debug(cvsymbols) DbgIO.println("S_END");
261 if ( parent_scope !is null )
262 {
263 if ( parent_scope.parent_scope !is null )
264 parent_scope = parent_scope.parent_scope;
265 else
266 parent_scope = null;
267 }
268 else {
269 debug DbgIO.println("S_END with no active parent scope");
270 }
271 expecting_arguments = false;
272 break;
273 case SymbolIndex.S_ENDARG:
274 expecting_arguments = false;
275 break;
276 case SymbolIndex.S_RETURN:
277 dr.readA(buf, CVReturnSymbol.sizeof);
278 ReturnSymbol rsym = new ReturnSymbol(cast(CVReturnSymbol*)buf.ptr);
279 if ( rsym.cvdata.style == 1 ) {
280 ubyte count;
281 dr.read(count);
282 dr.readA!(ubyte)(rsym.registers, count);
283 }
284 ProcedureSymbol psym = cast(ProcedureSymbol)parent_scope;
285 assert(psym !is null);
286 psym.return_sym = rsym;
287 break;
288 case SymbolIndex.S_LPROC32:
289 case SymbolIndex.S_GPROC32:
290 dr.readA(buf, CVProcedureSymbol.sizeof);
291 ProcedureSymbol psym = new ProcedureSymbol(cast(SymbolIndex)index, symbol_start, cast(CVProcedureSymbol*)buf.ptr);
292 dr.read(psym.mangled_name);
293 psym.name_notype = demangleName(psym.mangled_name);
294 psym.name_type = demangle(psym.mangled_name);
295 debug(cvsymbols) DbgIO.println("PROC32 %s (%s) s:%x o:%x", psym.name_type, psym.name_notype, psym.cvdata.segment, psym.cvdata.offset);
296 scope_syms[symbol_start] = psym;
297 addSymbol(psym);
298 assert ( parent_scope is null || psym.cvdata.pParent==parent_scope.lfo );
299 if ( psym.cvdata.pParent in scope_syms )
300 {
301 psym.parent_scope = scope_syms[psym.cvdata.pParent];
302 psym.parent_scope.symbols.add(psym);
303 }
304 parent_scope = psym;
305 expecting_arguments = true;
306 break;
307 case SymbolIndex.S_BPREL32:
308 dr.readA(buf, CVStackSymbol.sizeof);
309 StackSymbol stsym = new StackSymbol(cast(CVStackSymbol*)buf.ptr);
310 dr.read(stsym.mangled_name);
311 stsym.name_notype = demangleName(stsym.mangled_name);
312 stsym.name_type = demangle(stsym.mangled_name);
313 debug(cvsymbols) DbgIO.println(
314 "BPREL32 %s%s [%s] 0x%x o:%d", parent_scope !is null?"("~parent_scope.name_type~") ":"",
315 stsym.name_type, stsym.name_notype, stsym.cvtype, cast(int)stsym.cvdata.offset
316 );
317 addSymbol(stsym);
318 break;
319 case SymbolIndex.S_LDATA32:
320 case SymbolIndex.S_GDATA32:
321 case SymbolIndex.S_PUB32:
322 dr.readA(buf, CVDataSymbol.sizeof);
323 DataSymbol dsym = new DataSymbol(cast(SymbolIndex)index, cast(CVDataSymbol*)buf.ptr);
324 dr.read(dsym.mangled_name);
325 dsym.name_notype = demangleName(dsym.mangled_name);
326 dsym.name_type = demangle(dsym.mangled_name);
327 debug(cvsymbols) DbgIO.println("[LG]DATA|PUB32 %s (%s) s:%x o:%x t:0x%x", dsym.name_type, dsym.name_notype, dsym.cvdata.segment, dsym.offset, dsym.cvtype);
328 addSymbol(dsym);
329 break;
330 case SymbolIndex.S_ALIGN:
331 debug(cvsymbols) DbgIO.println("ALIGN");
332 break;
333 case SymbolIndex.S_UDT:
334 UserDefinedType udt = new UserDefinedType;
335 dr.read(udt.type_index);
336 dr.read(udt.name);
337 cv.udtypes ~= udt;
338 break;
339 case SymbolIndex.S_PROCREF:
340 case SymbolIndex.S_DATAREF:
341 break;
342 case SymbolIndex.S_REGISTER:
343 case SymbolIndex.S_CONSTANT:
344 case SymbolIndex.S_SKIP:
345 case SymbolIndex.S_CVRESERVE:
346 case SymbolIndex.S_OBJNAME:
347 case SymbolIndex.S_COBOLUDT:
348 case SymbolIndex.S_MANYREG:
349 case SymbolIndex.S_ENTRYTHIS:
350 case SymbolIndex.S_BPREL16:
351 case SymbolIndex.S_LDATA16:
352 case SymbolIndex.S_PUB16:
353 case SymbolIndex.S_LPROC16:
354 case SymbolIndex.S_GPROC16:
355 case SymbolIndex.S_THUNK16:
356 case SymbolIndex.S_BLOCK16:
357 case SymbolIndex.S_WITH16:
358 case SymbolIndex.S_LABEL16:
359 case SymbolIndex.S_CEXMODEL16:
360 case SymbolIndex.S_VFTPATH16:
361 case SymbolIndex.S_REGREL16:
362 case SymbolIndex.S_GDATA16:
363 case SymbolIndex.S_THUNK32:
364 case SymbolIndex.S_BLOCK32:
365 case SymbolIndex.S_WITH32:
366 case SymbolIndex.S_LABEL32:
367 case SymbolIndex.S_CEXMODEL32:
368 case SymbolIndex.S_VFTPATH32:
369 case SymbolIndex.S_REGREL32:
370 case SymbolIndex.S_LTHREAD32:
371 case SymbolIndex.S_GTHREAD32:
372 debug DbgIO.println("unprocessed symbol index 0x%x", index);
373 break;
374 default:
375 debug DbgIO.println("unknown symbol index 0x%x", index);
376 }
377
378 dr.seek(next_symbol);
379 }
380 }
381
382 /**********************************************************************************************
383
384 **********************************************************************************************/
385 void parseSrcModule(CodeView cv, ubyte[] data, Module mod)
386 {
387 if ( data.length <= 0 )
388 throw new CodeViewException("parseSrcModule on empty data");
389 DataReader dr = new DataReader(data);
390 ushort cFile, cSeg;
391 dr.read(cFile);
392 dr.read(cSeg);
393
394 SourceModule smod = new SourceModule;
395 mod.source_module = smod;
396 cv.source_modules ~= smod;
397
398 uint[] baseSrcFile,
399 start_end;
400 ushort[] seginds;
401 dr.readA(baseSrcFile, cast(uint)cFile);
402 dr.readA(start_end, cast(uint)cSeg*2);
403 dr.readA(seginds, cast(uint)cSeg);
404 debug(cvparser) DbgIO.println("Module %s files=%d segs=%d", mod.name, cFile, cSeg);
405
406 foreach ( fileoffset; baseSrcFile )
407 {
408 dr.seek(fileoffset);
409 dr.read(cSeg);
410 ushort pad;
411 dr.read(pad);
412
413 SourceFile file = new SourceFile;
414 file.source_module = smod;
415 uint[] baseSrcLn;
416 dr.readA(baseSrcLn, cast(uint)cSeg);
417 start_end = null;
418 dr.readA(start_end, cast(uint)cSeg*2);
419 dr.read(file.name);
420 debug(cvparser) DbgIO.println("\tFile %s segs=%d", file.name, cSeg);
421 smod.files ~= file;
422
423 foreach ( int i, segoff; baseSrcLn )
424 {
425 dr.seek(segoff);
426 SourceSegment seg = new SourceSegment;
427 file.segments ~= seg;
428 seg.file = file;
429
430 seg.start = start_end[i*2];
431 seg.end = start_end[i*2+1];
432
433 dr.read(pad); // segment index
434 ushort cPair;
435 dr.read(cPair);
436 debug(cvparser) DbgIO.println("\t\tSegment %d lines=%d", file.segments.length-1, cPair);
437
438 uint[] offset;
439 ushort[] linenumber;
440 dr.readA(offset, cast(uint)cPair);
441 dr.readA(linenumber, cast(uint)cPair);
442
443 foreach ( int j, l; linenumber ) {
444 CodeBlock cb = new CodeBlock(offset[j], l, seg);
445 file.blocks_by_line[l] ~= cb;
446 debug(cvparser)
447 {
448 bool inserted = cv.codeblocks.insert(cb);
449 if ( !inserted )
450 DbgIO.println("failed to insert block %s, already exists", cb);
451 }
452 else
453 cv.codeblocks.insert(cb);
454 }
455 }
456
457 file.lines = file.blocks_by_line.keys.dup.sort;
458 }
459 }
460
461 /**********************************************************************************************
462
463 **********************************************************************************************/
464 void parseLibraries(CodeView cv, ubyte[] data)
465 {
466 if ( data.length <= 0 )
467 throw new CodeViewException("parseLibraries on empty data");
468 DataReader dr = new DataReader(data);
469 while ( dr.available ) {
470 string lib;
471 dr.read(lib);
472 cv.libraries ~= lib;
473 }
474 }
475
476 /**********************************************************************************************
477
478 **********************************************************************************************/
479 void parsePackedSymbols(CodeView cv, ubyte[] data, SymbolSet symbols)
480 {
481 if ( data.length <= 0 )
482 throw new CodeViewException("parsePackedSymbols on empty data");
483 DataReader dr = new DataReader(data);
484
485 ubyte[] buf;
486 dr.readA(buf, PackedSymbolsHeader.sizeof);
487 PackedSymbolsHeader* gsh = cast(PackedSymbolsHeader*)buf.ptr;
488
489 dr.readA(buf, gsh.cbSymbol);
490 parseSymbols(cv, buf, symbols);
491 }
492
493 /**********************************************************************************************
494
495 **********************************************************************************************/
496 void parseGlobalTypes(CodeView cv, ubyte[] data, uint absolute_offset)
497 {
498 DataReader dr = new DataReader(data);
499 uint flags,
500 cType;
501 uint[] offType;
502 dr.read(flags);
503 dr.read(cType);
504 dr.readA(offType, cType);
505
506 uint base = dr.cursor;
507 foreach ( off; offType )
508 {
509 dr.seek(base+off);
510 ushort len;
511 dr.read(len);
512 ubyte[] buf;
513 dr.readA(buf, cast(uint)len);
514 cv.type_strings ~= parseTypeString(cv, buf);
515 }
516 }
517
518 /**********************************************************************************************
519
520 **********************************************************************************************/
521 Leaf[] parseTypeString(CodeView cv, ubyte[] data)
522 {
523 debug(cvdump) foreach ( b; data )
524 DbgIO.print("%02x ", b);
525 debug(cvdump) DbgIO.println("");
526 DataReader dr = new DataReader(data);
527 Leaf[] leafs;
528 bool first = true;
529 while ( dr.available )
530 {
531 ushort leaf_index;
532 dr.read(leaf_index);
533 Leaf l;
534 // debug(cvparser) DbgIO.println("parsing 0x%x", leaf_index);
535 switch ( leaf_index )
536 {
537 case LF_MODIFIER_16t:
538 LeafModifer lm = new LeafModifer;
539 l = lm;
540 dr.read(lm.attribute);
541 dr.read(lm.index);
542 break;
543 case LF_POINTER_16t:
544 LeafPointer lp = new LeafPointer;
545 l = lp;
546 dr.read(lp.attribute);
547 dr.read(lp.type);
548 switch ( lp.attribute&0x1f )
549 {
550 case 0:
551 case 10:
552 break;
553 default:
554 debug DbgIO.println("unprocessed pointer type: 0x%x", lp.attribute);
555 assert(0);
556 }
557 break;
558 case LF_ARRAY_16t:
559 LeafArray la = new LeafArray;
560 l = la;
561 dr.read(la.elemtype);
562 dr.read(la.idxtype);
563 la.length = parseNumericLeaf(dr);
564 dr.read(la.name);
565 debug(cvparser) DbgIO.println("LF_ARRAY: %d 0x%x", la.length.getUint, 0x1000+cv.type_strings.length);
566 break;
567 case LF_PROCEDURE_16t:
568 LeafProcedure lp = new LeafProcedure;
569 l = lp;
570 dr.read(lp.rvtype);
571 dr.read(lp.call);
572 dr.read(lp.reserved);
573 dr.read(lp.cParms);
574 dr.read(lp.arglist);
575 break;
576 case LF_MFUNCTION_16t:
577 LeafMFunction lmf = new LeafMFunction;
578 l = lmf;
579 dr.read(lmf.rvtype);
580 dr.read(lmf._class);
581 dr.read(lmf._this);
582 dr.read(lmf.call);
583 dr.read(lmf.reserved);
584 dr.read(lmf.cParms);
585 dr.read(lmf.arglist);
586 dr.read(lmf.thisadjust);
587 break;
588 case LF_VTSHAPE:
589 LeafVTShape lvts = new LeafVTShape;
590 l = lvts;
591 ushort count;
592 dr.read(count);
593 dr.readA(lvts.descriptor, cast(uint)(count+1)>>1);
594 // skip rest of typestring
595 dr.seek(dr.data.length);
596 break;
597 case LF_CLASS_16t:
598 case LF_STRUCTURE_16t:
599 LeafClassStruc lcs = new LeafClassStruc;
600 l = lcs;
601 dr.read(lcs.count);
602 dr.read(lcs.field);
603 dr.read(lcs.property);
604 dr.read(lcs.dList);
605 dr.read(lcs.vshape);
606 lcs.length = parseNumericLeaf(dr);
607 dr.read(lcs.name);
608 lcs.type = cast(ushort)(0x1000+cv.type_strings.length);
609 debug(cvparser) DbgIO.println(
610 "%s 0x%x '%s' fl: 0x%x prop: 0x%x, length=0x%x", leaf_index==LF_CLASS_16t?"class":"struct",
611 lcs.type, lcs.name, lcs.field, lcs.property, lcs.length.getUint
612 );
613
614 cv.UDTsByName[lcs.name] = lcs;
615 break;
616 case LF_ENUM_16t:
617 LeafEnum le = new LeafEnum;
618 l = le;
619 dr.read(le.count);
620 dr.read(le.type);
621 dr.read(le.field);
622 dr.read(le.property);
623 dr.read(le.name);
624 debug(cvparser) DbgIO.println(
625 "enum 0x%x '%s' type: 0x%x fl: 0x%x prop: 0x%x", 0x1000+cv.type_strings.length, le.name, le.type, le.field, le.property
626 );
627 cv.UDTsByName[le.name] = le;
628 break;
629 case LF_UNION_16t:
630 LeafUnion lu = new LeafUnion;
631 l = lu;
632 dr.read(lu.count);
633 dr.read(lu.field);
634 dr.read(lu.property);
635 lu.length = parseNumericLeaf(dr);
636 dr.read(lu.name);
637 // skip rest of typestring
638 dr.seek(dr.data.length);
639 debug(cvparser) DbgIO.println("Union '%s' count %d fields 0x%x length 0x%x", lu.name, lu.count, lu.field, lu.length.getUint);
640 cv.UDTsByName[lu.name] = lu;
641 break;
642 case LF_OEM_16t:
643 ushort oem;
644 dr.read(oem);
645 assert(oem == OEM_DIGITALMARS);
646 dr.read(oem);
647 ushort count;
648 dr.read(count);
649 assert(count == 2);
650 switch ( oem )
651 {
652 case D_DYN_ARRAY:
653 LeafDynArray lda = new LeafDynArray;
654 l = lda;
655 dr.read(lda.index_type);
656 dr.read(lda.elem_type);
657 debug(cvparser) DbgIO.println("Dynamic array index_type 0x%x elem_type 0x%x", lda.index_type, lda.elem_type);
658 break;
659 case D_ASSOC_ARRAY:
660 LeafAssocArray laa = new LeafAssocArray;
661 l = laa;
662 dr.read(laa.key_type);
663 dr.read(laa.elem_type);
664 debug(cvparser) DbgIO.println("Associativ array key_type 0x%x elem_type 0x%x", laa.key_type, laa.elem_type);
665 break;
666 default:
667 LeafDelegate ld = new LeafDelegate;
668 l = ld;
669 dr.read(ld.this_type);
670 dr.read(ld.func_type);
671 debug(cvparser) DbgIO.println("Delegate this_type 0x%x func_type 0x%x", ld.this_type, ld.func_type);
672 break;
673 }
674 break;
675
676 case LF_ARGLIST_16t:
677 LeafArgList lal = new LeafArgList;
678 l = lal;
679 dr.read(lal.argcount);
680 dr.readA(lal.indeces, cast(uint)lal.argcount);
681 break;
682 case LF_FIELDLIST_16t:
683 debug(cvparser) DbgIO.println("fieldlist 0x%x", 0x1000+cv.type_strings.length);
684 LeafFieldList lfl = new LeafFieldList;
685 l = lfl;
686 while ( dr.available )
687 lfl.fields ~= parseSubfield(dr);
688 // skip rest of typestring
689 dr.seek(dr.data.length);
690 break;
691 case LF_DERIVED_16t:
692 LeafDerived ld = new LeafDerived;
693 l = ld;
694 ushort count;
695 dr.read(count);
696 dr.readA(ld.types, cast(uint)count);
697 break;
698 case LF_METHODLIST_16t:
699 LeafMethodList lml = new LeafMethodList;
700 l = lml;
701 // skip rest of typestring
702 dr.seek(dr.data.length);
703 break;
704 default:
705 debug DbgIO.println("unprocessed leaf index 0x%x at 0x%x", leaf_index, dr.cursor-2);
706 l = new Leaf;
707 }
708 assert ( l !is null );
709 l.leaf_index = leaf_index;
710 leafs ~= l;
711 }
712 return leafs;
713 }
714
715 /**********************************************************************************************
716
717 **********************************************************************************************/
718 Leaf parseSubfield(DataReader dr)
719 {
720 ushort leaf_index;
721 dr.read(leaf_index);
722 Leaf l;
723 switch ( leaf_index )
724 {
725 case LF_BCLASS_16t:
726 LeafBaseClass lbc = new LeafBaseClass;
727 l = lbc;
728 dr.read(lbc.type);
729 dr.read(lbc.attribute);
730 lbc.offset = parseNumericLeaf(dr);
731 debug(cvparser) DbgIO.println("SFbclass");
732 break;
733 case LF_MEMBER_16t:
734 LeafMember lm = new LeafMember;
735 l = lm;
736 dr.read(lm.type);
737 dr.read(lm.attribute);
738 lm.offset = parseNumericLeaf(dr);
739 dr.read(lm.name);
740 debug(cvparser) DbgIO.println("SFmember: %s", lm.name);
741 break;
742 case LF_METHOD_16t:
743 LeafMethod lm = new LeafMethod;
744 l = lm;
745 dr.read(lm.count);
746 dr.read(lm.mList);
747 dr.read(lm.name);
748 debug(cvparser) DbgIO.println("SFmethod: %d 0x%x %s", lm.count, lm.mList, lm.name);
749 break;
750 case LF_ENUMERATE:
751 LeafEnumNameValue le = new LeafEnumNameValue;
752 l = le;
753 dr.read(le.attribute);
754 le.value = parseNumericLeaf(dr);
755 dr.read(le.name);
756 debug(cvparser) DbgIO.println("SFenumerate: %s %d", le.name, le.value.getUint);
757 break;
758 case LF_NESTTYPE_16t:
759 LeafNestedType ln = new LeafNestedType;
760 l = ln;
761 dr.read(ln.index);
762 dr.read(ln.name);
763 debug(cvparser) DbgIO.println("SFnesttype: %s", ln.name);
764 break;
765 case LF_STMEMBER_16t:
766 LeafStaticDataMember ls = new LeafStaticDataMember;
767 l = ls;
768 dr.read(ls.type);
769 dr.read(ls.attribute);
770 dr.read(ls.name);
771 debug(cvparser) DbgIO.println("SFstmember: %s", ls.name);
772 break;
773 case LF_SKIP_16t:
774 dr.seek(dr.data.length);
775 debug(cvparser) DbgIO.println("SFskip");
776 break;
777 default:
778 debug DbgIO.println("unprocessed subfield index 0x%x", leaf_index);
779 l = new Leaf;
780 }
781 if ( dr.available )
782 {
783 ubyte pad;
784 dr.peek(pad);
785 if ( pad > 0xf0 )
786 dr.relseek(pad&0xf);
787 }
788 assert ( l !is null );
789 l.leaf_index = leaf_index;
790 return l;
791 }
792
793 /**********************************************************************************************
794
795 **********************************************************************************************/
796 LeafNumeric parseNumericLeaf(DataReader dr)
797 {
798 LeafNumeric nl = new LeafNumeric;
799 dr.read(nl.leaf_index);
800 if ( nl.leaf_index < 0x8000 ) {
801 nl.us = cast(ushort)nl.leaf_index;
802 nl.leaf_index = LF_USHORT;
803 }
804 else switch ( nl.leaf_index )
805 {
806 case LF_VARSTRING: dr.read(nl.str); break;
807 case LF_CHAR: dr.read(nl.c); break;
808 case LF_SHORT: dr.read(nl.s); break;
809 case LF_USHORT: dr.read(nl.us); break;
810 case LF_LONG: dr.read(nl.i); break;
811 case LF_ULONG: dr.read(nl.ui); break;
812 case LF_REAL32: dr.read(nl.f); break;
813 case LF_REAL64: dr.read(nl.d); break;
814 case LF_REAL80: dr.read(nl.r); break;
815 case LF_QUADWORD: dr.read(nl.l); break;
816 case LF_UQUADWORD: dr.read(nl.ul); break;
817 case LF_COMPLEX32: dr.read(nl.cf); break;
818 case LF_COMPLEX64:
819 case LF_COMPLEX80:
820 case LF_REAL48:
821 case LF_COMPLEX128:
822 case LF_REAL128:
823 default:
824 debug DbgIO.println("unknown leaftype %x", nl.leaf_index);
825 }
826 return nl;
827 }
828
829 /**********************************************************************************************
830 Updates symbol size fields and mangled_names. Since both can only
831 be determined fully after sstGlobalTypes have been read.
832 **********************************************************************************************/
833 void updateSymbols(CodeView cv, NamedSymbol[] syms)
834 {
835 foreach ( s; syms )
836 {
837 if ( s.mangled_name is null || s.mangled_name.length <= 0 )
838 s.mangled_name = cv.mangle(s);
839
840 ScopeSymbol scs = cast(ScopeSymbol)s;
841 if ( scs !is null )
842 updateSymbols(cv, scs.symbols.named_symbols);
843 ProcedureSymbol ps = cast(ProcedureSymbol)s;
844 if ( ps !is null )
845 updateSymbols(cv, ps.arguments.named_symbols);
846
847 string type = cv.mangleType(s);
848 if ( type is null )
849 continue;
850
851 DataSymbol ds = cast(DataSymbol)s;
852 if ( ds !is null )
853 ds.size = cv.sizeofCV(ds.cvdata.type);
854 else
855 {
856 StackSymbol ss = cast(StackSymbol)s;
857 if ( ss !is null )
858 ss.size = cv.sizeofCV(ss.cvdata.type);
859 }
860 }
861 }
862 }