Mercurial > projects > ddbg_continued
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 } |