Mercurial > projects > ddbg_continued
comparison src/codeview/codeview.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 | a5fb1bc967e6 |
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.codeview; | |
7 | |
8 import std.ctype; | |
9 import std.string; | |
10 import std.math; | |
11 | |
12 import util; | |
13 import container; | |
14 import codeview.coff; | |
15 import codeview.decl; | |
16 | |
17 public import codeview.debuginfo; | |
18 | |
19 //================================================================================================= | |
20 // classes for accessing CodeView data | |
21 | |
22 abstract class Symbol | |
23 { | |
24 SymbolIndex symbol_index; | |
25 | |
26 this(SymbolIndex si) { symbol_index = si; } | |
27 } | |
28 | |
29 class ReturnSymbol : Symbol | |
30 { | |
31 CVReturnSymbol* cvdata; | |
32 ubyte[] registers; | |
33 | |
34 this(CVReturnSymbol* cv) { super(SymbolIndex.S_RETURN); cvdata = cv; } | |
35 } | |
36 | |
37 class StringWrap | |
38 { | |
39 string str; | |
40 | |
41 this(string _str) { str = _str; } | |
42 | |
43 int opCmp(Object o) | |
44 { | |
45 NamedSymbol ns = cast(NamedSymbol)o; | |
46 if ( ns !is null ) | |
47 return -ns.opCmp(this); | |
48 | |
49 StringWrap sw = cast(StringWrap)o; | |
50 if ( sw is null ) | |
51 return -1; | |
52 if ( str == sw.str ) | |
53 return 0; | |
54 if ( str < sw.str ) | |
55 return -1; | |
56 return 1; | |
57 } | |
58 } | |
59 | |
60 abstract class NamedSymbol : Symbol | |
61 { | |
62 string mangled_name, | |
63 name_type, | |
64 name_notype; | |
65 | |
66 this(SymbolIndex si) { super(si); } | |
67 | |
68 int opCmp(Object o) | |
69 { | |
70 string str; | |
71 NamedSymbol ns = cast(NamedSymbol)o; | |
72 if ( ns is null ) | |
73 { | |
74 StringWrap sw = cast(StringWrap)o; | |
75 if ( sw is null ) | |
76 return -1; | |
77 str = sw.str; | |
78 } | |
79 else | |
80 str = ns.name_notype; | |
81 if ( name_notype == str ) | |
82 return 0; | |
83 if ( name_notype < str ) | |
84 return -1; | |
85 return 1; | |
86 } | |
87 } | |
88 | |
89 class StackSymbol : NamedSymbol | |
90 { | |
91 CVStackSymbol* cvdata; | |
92 int size; | |
93 | |
94 this(CVStackSymbol* cv) | |
95 { | |
96 super(SymbolIndex.S_BPREL32); | |
97 cvdata=cv; | |
98 } | |
99 | |
100 uint offset() { return cvdata.offset; } | |
101 uint cvtype() { return cvdata.type; } | |
102 } | |
103 | |
104 class DataSymbol : NamedSymbol | |
105 { | |
106 CVDataSymbol* cvdata; | |
107 uint size; | |
108 | |
109 this(SymbolIndex si, CVDataSymbol* cv) | |
110 { | |
111 super(si); | |
112 cvdata=cv; | |
113 } | |
114 | |
115 uint offset() { return cvdata.offset; } | |
116 uint cvtype() { return cvdata.type; } | |
117 } | |
118 | |
119 abstract class ScopeSymbol : NamedSymbol | |
120 { | |
121 ScopeSymbol parent_scope; | |
122 SymbolSet symbols; | |
123 uint lfo; | |
124 | |
125 this(SymbolIndex si, uint _lfo) { super(si); lfo = _lfo; symbols = new SymbolSet; } | |
126 } | |
127 | |
128 class ProcedureSymbol : ScopeSymbol | |
129 { | |
130 CVProcedureSymbol* cvdata; | |
131 SymbolSet arguments; | |
132 ReturnSymbol return_sym; | |
133 | |
134 this(SymbolIndex si, uint lfo, CVProcedureSymbol* cvd) | |
135 { | |
136 super(si,lfo); | |
137 cvdata = cvd; | |
138 arguments = new SymbolSet; | |
139 } | |
140 } | |
141 | |
142 class SymbolSet | |
143 { | |
144 ProcedureSymbol[] proc_symbols; | |
145 StackSymbol[] stack_symbols; | |
146 DataSymbol[] data_symbols; | |
147 NamedSymbol[] named_symbols; | |
148 Symbol[] symbols; | |
149 | |
150 void opCatAssign(SymbolSet s) | |
151 { | |
152 symbols ~= s.symbols; | |
153 named_symbols ~= s.named_symbols; | |
154 data_symbols ~= s.data_symbols; | |
155 stack_symbols ~= s.stack_symbols; | |
156 proc_symbols ~= s.proc_symbols; | |
157 } | |
158 | |
159 void add(Symbol s) | |
160 { | |
161 NamedSymbol ns = cast(NamedSymbol)s; | |
162 if ( ns is null ) { | |
163 symbols ~= s; | |
164 return; | |
165 } | |
166 named_symbols ~= ns; | |
167 ClassInfo ci = s.classinfo; | |
168 if ( ci == ProcedureSymbol.classinfo ) | |
169 proc_symbols ~= cast(ProcedureSymbol)s; | |
170 else if ( ci == StackSymbol.classinfo ) | |
171 stack_symbols ~= cast(StackSymbol)s; | |
172 else if ( ci == DataSymbol.classinfo ) | |
173 data_symbols ~= cast(DataSymbol)s; | |
174 } | |
175 | |
176 /********************************************************************************************** | |
177 Find procedure symbol covering the given address. | |
178 **********************************************************************************************/ | |
179 ProcedureSymbol findProcedureSymbol(uint address) | |
180 { | |
181 foreach ( ps; proc_symbols ) | |
182 if ( address >= ps.cvdata.offset && address < ps.cvdata.offset+ps.cvdata.proc_length ) | |
183 return ps; | |
184 return null; | |
185 } | |
186 | |
187 /********************************************************************************************** | |
188 Find data symbol covering the given address. | |
189 **********************************************************************************************/ | |
190 DataSymbol findDataSymbol(uint address, uint segment) | |
191 { | |
192 foreach ( ds; data_symbols ) | |
193 { | |
194 if ( segment > 0 && ds.cvdata.segment != segment ) | |
195 continue; | |
196 if ( address == ds.cvdata.offset ) | |
197 return ds; | |
198 } | |
199 return null; | |
200 } | |
201 | |
202 /********************************************************************************************** | |
203 Find data symbol by name. | |
204 **********************************************************************************************/ | |
205 DataSymbol findDataSymbol(string name) | |
206 { | |
207 foreach ( ds; data_symbols ) | |
208 { | |
209 if ( ds.name_notype == name ) | |
210 return ds; | |
211 } | |
212 return null; | |
213 } | |
214 | |
215 /********************************************************************************************** | |
216 Find nearest data symbol to the given address. | |
217 **********************************************************************************************/ | |
218 DataSymbol findNearestDataSymbol(uint address, inout uint min_dist, uint segment) | |
219 { | |
220 DataSymbol min_ds; | |
221 foreach ( ds; data_symbols ) | |
222 { | |
223 if ( address < ds.cvdata.offset || ds.cvdata.segment != segment ) | |
224 continue; | |
225 uint dist = abs(cast(int)address-cast(int)ds.cvdata.offset); | |
226 if ( dist < min_dist ) { | |
227 min_dist = dist; | |
228 min_ds = ds; | |
229 } | |
230 } | |
231 return min_ds; | |
232 } | |
233 } | |
234 | |
235 class Module | |
236 { | |
237 ModuleHeader* header; | |
238 SegInfo[] seginfos; | |
239 string name; | |
240 ushort pe_section; | |
241 | |
242 SymbolSet symbols; | |
243 | |
244 SourceModule source_module; | |
245 | |
246 CodeView codeview; | |
247 | |
248 this(CodeView cv) | |
249 { | |
250 symbols = new SymbolSet; | |
251 codeview = cv; | |
252 } | |
253 } | |
254 | |
255 class Location | |
256 { | |
257 string path; | |
258 | |
259 ScopeSymbol scope_sym; | |
260 DataSymbol data_sym; | |
261 Module mod; | |
262 CodeBlock codeblock; | |
263 CodeView codeview; | |
264 uint address; | |
265 | |
266 this(uint addr, CodeView cv) | |
267 { | |
268 codeview = cv; | |
269 address = addr; | |
270 } | |
271 | |
272 this(uint addr) | |
273 { | |
274 address = addr; | |
275 } | |
276 | |
277 this(string p) | |
278 { | |
279 path = p; | |
280 } | |
281 | |
282 uint line() | |
283 { | |
284 if ( codeblock is null ) | |
285 return 0; | |
286 return codeblock.line; | |
287 } | |
288 | |
289 string file() | |
290 { | |
291 if ( codeblock is null || codeblock.segment is null ) | |
292 return null; | |
293 return codeblock.segment.file.name; | |
294 } | |
295 | |
296 size_t getCodeBase() | |
297 { | |
298 return mod.codeview.image.getCodeBase; | |
299 } | |
300 | |
301 bool bind(ImageSet images, string[] source_search_paths) | |
302 { | |
303 if ( path is null ) | |
304 return false; | |
305 | |
306 if ( find(path, '"') >= 0 ) | |
307 path = replace(path, "\"", ""); | |
308 | |
309 string[] file_line = split(path, ":"); | |
310 if ( file_line is null || file_line.length < 2 || !isNumeric(file_line[$-1]) ) { | |
311 DbgIO.println("Invalid location format. Use <part of filename>:<linenumber>"); | |
312 return false; | |
313 } | |
314 | |
315 string file = join(file_line[0..$-1], ":"), | |
316 line = file_line[$-1]; | |
317 | |
318 if ( find(file, '/') >= 0 ) | |
319 file = replace(file, "/", "\\"); | |
320 | |
321 SourceFile[] sfs = images.findSrcFiles(file); | |
322 if ( sfs.length == 0 ) | |
323 sfs = images.findSrcFiles(file, source_search_paths); | |
324 if ( sfs.length == 0 ) { | |
325 DbgIO.println("Source file \"%s\" not found", file); | |
326 return false; | |
327 } | |
328 | |
329 uint linenum = cast(uint)atoi(line); | |
330 Location loc; | |
331 foreach ( sf; sfs ) | |
332 { | |
333 debug DbgIO.println("searching sf %s", sf.name); | |
334 auto loc2 = images.findSrcLine(sf, linenum); | |
335 if ( loc is null ) | |
336 loc = loc2; | |
337 else if ( loc2 !is null && loc2.line < loc.line ) | |
338 loc = loc2; | |
339 } | |
340 if ( loc is null ) | |
341 DbgIO.println("Line %d in \"%s\" not found", linenum, sfs[0].name); | |
342 | |
343 scope_sym = loc.scope_sym; | |
344 data_sym = loc.data_sym; | |
345 mod = loc.mod; | |
346 codeblock = loc.codeblock; | |
347 address = loc.address; | |
348 path = null; | |
349 return true; | |
350 } | |
351 } | |
352 | |
353 class UserDefinedType | |
354 { | |
355 ushort type_index; | |
356 string name; | |
357 } | |
358 | |
359 /************************************************************************************************** | |
360 Represents the CodeView information of an executable image. Provides methods to browse the | |
361 information. Objects of this class get created by CodeViewParser.parse. | |
362 **************************************************************************************************/ | |
363 class CodeView : DebugInfo | |
364 { | |
365 Module[string] modulesByName; | |
366 Module[] modulesByIndex; | |
367 | |
368 SymbolSet global_pub, | |
369 global_sym, | |
370 static_sym; | |
371 UserDefinedType[] udtypes; | |
372 Leaf[][] type_strings; | |
373 | |
374 Leaf[string] UDTsByName; | |
375 | |
376 string[] libraries, | |
377 segnames; | |
378 | |
379 COFFImage image; | |
380 | |
381 AVLTree!(NamedSymbol) globalNamedSymbols; | |
382 | |
383 size_t getCodeBase() | |
384 { | |
385 return image.getCodeBase; | |
386 } | |
387 | |
388 /********************************************************************************************** | |
389 Find the module and segment covering the given address. | |
390 **********************************************************************************************/ | |
391 Module findModule(uint vaddress, out uint segment) | |
392 { | |
393 uint address = vaddress-image.getCodeBase; | |
394 foreach ( m; modulesByIndex ) | |
395 { | |
396 foreach ( s; m.seginfos ) | |
397 { | |
398 if ( address < s.offset ) | |
399 continue; | |
400 if ( address-s.offset < s.cbSeg ) { | |
401 segment = s.Seg; | |
402 return m; | |
403 } | |
404 } | |
405 } | |
406 return null; | |
407 } | |
408 | |
409 /********************************************************************************************** | |
410 Find next source line from the given location. | |
411 **********************************************************************************************/ | |
412 Location findNextSrcLine(Location loc) | |
413 { | |
414 if ( loc is null || loc.codeblock is null || loc.codeblock.segment is null ) | |
415 return null; | |
416 Location nextloc = findLocation(loc.codeblock.end+image.getCodeBase); | |
417 return nextloc; | |
418 } | |
419 | |
420 /********************************************************************************************** | |
421 Find previous source line from location that isn't covered by a source codeblock. | |
422 **********************************************************************************************/ | |
423 Location findPrevSrcLine(Location loc) | |
424 { | |
425 if ( loc is null ) | |
426 return null; | |
427 if ( loc.codeblock !is null ) | |
428 return loc; | |
429 | |
430 AVLNode!(CodeBlock) node; | |
431 if ( !codeblocks.find(loc.address-1+image.getCodeBase, node) ) | |
432 { | |
433 if ( node.value.start > loc.address ) | |
434 { | |
435 if ( !node.findPrev(node) ) | |
436 return null; | |
437 } | |
438 } | |
439 Location prevloc = new Location(node.value.start, this); | |
440 prevloc.codeblock = node.value; | |
441 findSymbolForLocation(prevloc); | |
442 assert(prevloc.line != 0); | |
443 return prevloc; | |
444 } | |
445 | |
446 /********************************************************************************************** | |
447 Find first source line in the given file that has a line number >= line | |
448 and a start address >= min_start. | |
449 **********************************************************************************************/ | |
450 Location findSrcLine(SourceFile sf, uint min_line, size_t min_start=0) | |
451 { | |
452 if ( sf is null ) | |
453 return null; | |
454 | |
455 pragma(msg, TODO(__FILE__,__LINE__,"use binary search here")); | |
456 foreach ( l; sf.lines ) | |
457 { | |
458 if ( l < min_line ) | |
459 continue; | |
460 foreach ( cb; sf.blocks_by_line[l] ) | |
461 { | |
462 if ( cb.start < min_start || cb.end <= cb.start ) | |
463 continue; | |
464 Location loc = new Location(cb.start+image.getCodeBase, this); | |
465 loc.codeblock = cb; | |
466 findSymbolForLocation(loc); | |
467 return loc; | |
468 } | |
469 } | |
470 return null; | |
471 } | |
472 | |
473 /********************************************************************************************** | |
474 Find all debug information available for the given address. | |
475 **********************************************************************************************/ | |
476 Location findLocation(uint vaddress) | |
477 { | |
478 Location loc = new Location(vaddress, this); | |
479 CodeBlock cb = findCodeBlockAbs(vaddress); | |
480 loc.codeblock = cb; | |
481 findSymbolForLocation(loc); | |
482 return loc; | |
483 } | |
484 | |
485 /********************************************************************************************** | |
486 Fill out symbol information (as opposed to source line information) in the given location. | |
487 **********************************************************************************************/ | |
488 void findSymbolForLocation(Location loc) | |
489 { | |
490 ProcedureSymbol psym = findProcedureSymbol(loc.address); | |
491 if ( psym !is null ) | |
492 loc.scope_sym = psym; | |
493 else | |
494 { | |
495 DataSymbol dsym = findDataSymbol(loc.address, 2); | |
496 if ( dsym !is null ) | |
497 loc.data_sym = dsym; | |
498 } | |
499 | |
500 uint seg; | |
501 Module mod = findModule(loc.address, seg); | |
502 if ( mod !is null ) | |
503 { | |
504 loc.mod = mod; | |
505 if ( loc.data_sym is null ) | |
506 { | |
507 uint min_dist = uint.max; | |
508 loc.data_sym = global_sym.findNearestDataSymbol(loc.address-image.getCodeBase, min_dist, image.code_section_index+1); | |
509 if ( loc.data_sym is null ) | |
510 loc.data_sym = global_pub.findNearestDataSymbol(loc.address-image.getCodeBase, min_dist, image.code_section_index+1); | |
511 } | |
512 } | |
513 } | |
514 | |
515 /********************************************************************************************** | |
516 Find procedure symbol covering the given address. | |
517 **********************************************************************************************/ | |
518 ProcedureSymbol findProcedureSymbol(uint vaddress) | |
519 { | |
520 uint address = vaddress-image.getCodeBase; | |
521 ProcedureSymbol ps; | |
522 foreach ( m; modulesByIndex ) | |
523 { | |
524 ps = m.symbols.findProcedureSymbol(address); | |
525 if ( ps !is null ) | |
526 return ps; | |
527 } | |
528 ps = global_sym.findProcedureSymbol(address); | |
529 if ( ps is null ) | |
530 ps = static_sym.findProcedureSymbol(address); | |
531 if ( ps is null ) | |
532 ps = global_pub.findProcedureSymbol(address); | |
533 return ps; | |
534 } | |
535 | |
536 /********************************************************************************************** | |
537 Find data symbol covering the given address. | |
538 **********************************************************************************************/ | |
539 DataSymbol findDataSymbol(uint vaddress, uint segment=0) | |
540 { | |
541 uint address = vaddress-image.getCodeBase; | |
542 DataSymbol ps; | |
543 foreach ( m; modulesByIndex ) | |
544 { | |
545 ps = m.symbols.findDataSymbol(address, segment); | |
546 if ( ps !is null ) | |
547 break; | |
548 } | |
549 ps = global_sym.findDataSymbol(address, segment); | |
550 if ( ps is null ) | |
551 ps = static_sym.findDataSymbol(address, segment); | |
552 if ( ps is null ) | |
553 ps = global_pub.findDataSymbol(address, segment); | |
554 return ps; | |
555 } | |
556 | |
557 /********************************************************************************************** | |
558 Creates a D mangled name from a CodeView symbol. | |
559 Uses available mangled type info if available, mangles CodeView type info else. | |
560 Returns: Symbol name with mangled type info. | |
561 **********************************************************************************************/ | |
562 string mangle(NamedSymbol s) | |
563 { | |
564 // use mangled typeinfo if available | |
565 if ( s.mangled_name !is null && s.mangled_name.length > 2 && s.mangled_name[0..2] == "_D" && isdigit(s.mangled_name[2]) ) | |
566 return s.mangled_name; | |
567 | |
568 return "_D"~mangleName(s.name_type)~mangleType(s); | |
569 } | |
570 | |
571 /********************************************************************************************** | |
572 Creates the type part of a D mangled name for a CodeView symbol. | |
573 **********************************************************************************************/ | |
574 string mangleType(Symbol s) | |
575 { | |
576 DataSymbol ds = cast(DataSymbol)s; | |
577 ushort cvtype; | |
578 if ( ds !is null ) | |
579 cvtype = ds.cvdata.type; | |
580 else | |
581 { | |
582 StackSymbol ss = cast(StackSymbol)s; | |
583 if ( ss !is null ) | |
584 cvtype = ss.cvdata.type; | |
585 else { | |
586 pragma(msg, TODO(__FILE__,__LINE__,"implement procedure symbol mangling")); | |
587 } | |
588 } | |
589 return mangleCVtype(cvtype); | |
590 } | |
591 | |
592 /********************************************************************************************** | |
593 Creates the type part of a D mangled name for a CodeView type index. | |
594 **********************************************************************************************/ | |
595 string mangleCVtype(ushort cvtype) | |
596 { | |
597 if ( cvtype >= 0x1000 ) | |
598 { | |
599 uint typeindex = cvtype-0x1000; | |
600 if ( typeindex >= type_strings.length ) { | |
601 debug DbgIO.println("undefined complex type 0x%x largest known type 0x%x", cvtype, type_strings.length-1); | |
602 return null; | |
603 } | |
604 Leaf[] typestring = type_strings[typeindex]; | |
605 | |
606 while ( typestring.length > 0 ) | |
607 { | |
608 switch ( typestring[0].leaf_index ) | |
609 { | |
610 case LF_MODIFIER_16t: | |
611 LeafModifer lm = cast(LeafModifer)typestring[0]; | |
612 assert ( lm !is null ); | |
613 return mangleCVtype(lm.index); | |
614 case LF_POINTER_16t: | |
615 LeafPointer lp = cast(LeafPointer)typestring[0]; | |
616 assert ( lp !is null ); | |
617 return "P"~mangleCVtype(lp.type); | |
618 // do not insert new cases here | |
619 case LF_CLASS_16t: | |
620 LeafClassStruc lcs = cast(LeafClassStruc)typestring[0]; | |
621 assert ( lcs !is null ); | |
622 return "C"~mangleName(lcs.name); | |
623 case LF_ARRAY_16t: | |
624 LeafArray la = cast(LeafArray)typestring[0]; | |
625 assert ( la !is null ); | |
626 debug(cvparser) DbgIO.println("Static array elemtype 0x%x idxtype 0x%x length %d", la.elemtype, la.idxtype, la.length.getUint); | |
627 uint count = la.length.getUint, | |
628 elmsize = sizeofCV(la.elemtype); | |
629 if ( elmsize > 0 ) { | |
630 count /= elmsize; | |
631 assert(la.length.getUint % sizeofCV(la.elemtype) == 0); | |
632 } | |
633 else | |
634 debug DbgIO.println("WARNING: elm size == 0"); | |
635 return "G"~.toString(count)~mangleCVtype(la.elemtype); | |
636 case LF_OEM_16t: | |
637 LeafDynArray lda = cast(LeafDynArray)typestring[0]; | |
638 if ( lda !is null ) | |
639 return "A"~mangleCVtype(lda.elem_type); | |
640 LeafAssocArray laa = cast(LeafAssocArray)typestring[0]; | |
641 if ( laa !is null ) | |
642 return "H"~mangleCVtype(laa.key_type)~mangleCVtype(laa.elem_type); | |
643 LeafDelegate ld = cast(LeafDelegate)typestring[0]; | |
644 if ( ld !is null ) | |
645 return "D"~mangleCVtype(ld.func_type); | |
646 assert(0); | |
647 | |
648 case LF_STRUCTURE_16t: | |
649 LeafClassStruc lcs = cast(LeafClassStruc)typestring[0]; | |
650 assert ( lcs !is null ); | |
651 return "S"~mangleName(lcs.name); | |
652 case LF_PROCEDURE_16t: | |
653 case LF_METHODLIST_16t: | |
654 debug(cvparser) DbgIO.println("unmangled procedure or methodlist in complex type"); | |
655 return ""; | |
656 case LF_UNION_16t: | |
657 LeafUnion lu = cast(LeafUnion)typestring[0]; | |
658 return "S"~mangleName(lu.name); | |
659 default: | |
660 DbgIO.println("mangleCVtype: unsupported type leaf 0x%x", typestring[0].leaf_index); | |
661 typestring = typestring[1..$]; | |
662 } | |
663 } | |
664 return null; | |
665 } | |
666 | |
667 switch ( cvtype ) | |
668 { | |
669 case T_NOTYPE: | |
670 return null; | |
671 case T_VOID: | |
672 return "v"; | |
673 case T_PVOID: case T_PFVOID: case T_PHVOID: case T_32PVOID: case T_32PFVOID: | |
674 return "Pv"; | |
675 | |
676 case T_CHAR: | |
677 return "g"; | |
678 case T_UCHAR: | |
679 return "h"; | |
680 case T_RCHAR: | |
681 return "a"; | |
682 case T_WCHAR: | |
683 return "u"; | |
684 case T_DCHAR: | |
685 return "w"; | |
686 case T_32PDCHAR: case T_32PFDCHAR: | |
687 return "Pw"; | |
688 case T_PFRCHAR: case T_PHRCHAR: case T_32PRCHAR: case T_32PFRCHAR: case T_PRCHAR: | |
689 return "Pa"; | |
690 case T_PFWCHAR: case T_PHWCHAR: case T_32PWCHAR: case T_32PFWCHAR: case T_PWCHAR: | |
691 return "Pu"; | |
692 case T_PFCHAR: case T_PHCHAR: case T_32PCHAR: case T_32PFCHAR: case T_PCHAR: | |
693 return "Pg"; | |
694 case T_PFUCHAR: case T_PHUCHAR: case T_32PUCHAR: case T_32PFUCHAR: case T_PUCHAR: | |
695 return "Ph"; | |
696 | |
697 case T_SHORT: case T_INT2: | |
698 return "s"; | |
699 case T_USHORT: case T_UINT2: | |
700 return "t"; | |
701 case T_PINT2: case T_PSHORT: case T_32PSHORT: | |
702 return "Ps"; | |
703 case T_PUSHORT: case T_PUINT2: case T_32PUSHORT: | |
704 return "Pt"; | |
705 case T_INT4: | |
706 case T_LONG: | |
707 return "i"; | |
708 case T_UINT4: | |
709 case T_ULONG: | |
710 return "k"; | |
711 case T_32PINT4: case T_PINT4: | |
712 return "Pi"; | |
713 case T_32PUINT4: case T_PUINT4: | |
714 return "Pk"; | |
715 case T_QUAD: | |
716 return "l"; | |
717 case T_UQUAD: | |
718 return "m"; | |
719 case T_32PQUAD: case T_PQUAD: | |
720 return "Pl"; | |
721 case T_32PUQUAD: case T_PUQUAD: | |
722 return "Pm"; | |
723 case T_REAL32: | |
724 return "f"; | |
725 case T_32PREAL32: case T_PREAL32: | |
726 return "Pf"; | |
727 case T_REAL64: | |
728 return "d"; | |
729 case T_32PREAL64: case T_PREAL64: | |
730 return "Pd"; | |
731 case T_REAL80: | |
732 return "e"; | |
733 case T_PREAL80: case T_PFREAL80: case T_PHREAL80: case T_32PREAL80: case T_32PFREAL80: | |
734 return "Pe"; | |
735 case T_BOOL08: | |
736 return "b"; | |
737 case T_32PBOOL08: case T_32PFBOOL08: | |
738 return "Pb"; | |
739 case T_CPLX80: | |
740 return "c"; | |
741 case T_CPLX64: | |
742 return "r"; | |
743 case T_CPLX32: | |
744 return "q"; | |
745 case T_32PCPLX80: case T_32PFCPLX80: | |
746 return "Pc"; | |
747 case T_32PCPLX64: case T_32PFCPLX64: | |
748 return "Pr"; | |
749 case T_32PCPLX32: case T_32PFCPLX32: | |
750 return "Pq"; | |
751 default: | |
752 debug DbgIO.println("mangleCVtype: unknown codeview type 0x%x", cvtype); | |
753 } | |
754 return null; | |
755 } | |
756 | |
757 | |
758 /************************************************************************************************** | |
759 Returns: size of demangled type | |
760 **************************************************************************************************/ | |
761 uint sizeofMangled(string m) | |
762 { | |
763 assert(m.length > 0); | |
764 switch ( m[0] ) | |
765 { | |
766 case 'A': return ulong.sizeof; | |
767 case 'G': | |
768 string n = m[1..$]; | |
769 size_t count = parseNumber(n); | |
770 return count*sizeofMangled(n); | |
771 case 'P': return size_t.sizeof; | |
772 case 'H': return size_t.sizeof; | |
773 case 'v': return void.sizeof; | |
774 case 'b': return bit.sizeof; | |
775 case 'x': return bool.sizeof; | |
776 case 'g': return byte.sizeof; | |
777 case 'h': return ubyte.sizeof; | |
778 case 's': return short.sizeof; | |
779 case 't': return ushort.sizeof; | |
780 case 'i': return int.sizeof; | |
781 case 'k': return uint.sizeof; | |
782 case 'l': return long.sizeof; | |
783 case 'm': return ulong.sizeof; | |
784 case 'f': return float.sizeof; | |
785 case 'd': return double.sizeof; | |
786 case 'e': return real.sizeof; | |
787 case 'o': return ifloat.sizeof; | |
788 case 'p': return idouble.sizeof; | |
789 case 'j': return ireal.sizeof; | |
790 case 'q': return cfloat.sizeof; | |
791 case 'r': return cdouble.sizeof; | |
792 case 'c': return creal.sizeof; | |
793 case 'a': return char.sizeof; | |
794 case 'u': return wchar.sizeof; | |
795 case 'w': return dchar.sizeof; | |
796 case 'C': | |
797 case 'S': | |
798 string mangled_name = m[1..$], | |
799 name = demangleNameSkip(mangled_name); | |
800 if ( name in UDTsByName ) { | |
801 LeafClassStruc lcs = cast(LeafClassStruc)UDTsByName[name]; | |
802 if ( lcs !is null ) | |
803 return lcs.length.getUint; | |
804 LeafUnion lu = cast(LeafUnion)UDTsByName[name]; | |
805 if ( lu !is null ) | |
806 return lu.length.getUint; | |
807 } | |
808 assert(0, "unknown struct in sizeofMangled: "~name); | |
809 default: | |
810 assert(0, "unknown type in sizeofMangled: "~m); | |
811 } | |
812 return 0; | |
813 } | |
814 | |
815 | |
816 /********************************************************************************************** | |
817 Calculates the size of the type specified by a CodeView type index. | |
818 **********************************************************************************************/ | |
819 uint sizeofCV(uint cvtype) | |
820 { | |
821 if ( cvtype >= 0x1000 ) | |
822 { | |
823 uint typeindex = cvtype-0x1000; | |
824 if ( typeindex >= type_strings.length ) { | |
825 debug DbgIO.println("sizeofCV: undefined complex type 0x%x", cvtype); | |
826 return 0; | |
827 } | |
828 Leaf[] typestring = type_strings[typeindex]; | |
829 while ( typestring.length > 0 ) | |
830 { | |
831 switch ( typestring[0].leaf_index ) | |
832 { | |
833 case LF_MODIFIER_16t: | |
834 LeafModifer lm = cast(LeafModifer)typestring[0]; | |
835 assert ( lm !is null ); | |
836 return sizeofCV(lm.index); | |
837 case LF_ARRAY_16t: | |
838 LeafArray la = cast(LeafArray)typestring[0]; | |
839 assert ( la !is null ); | |
840 return la.length.getUint; | |
841 case LF_POINTER_16t: | |
842 case LF_CLASS_16t: | |
843 return 4; | |
844 case LF_STRUCTURE_16t: | |
845 LeafClassStruc lcs = cast(LeafClassStruc)typestring[0]; | |
846 assert ( lcs !is null ); | |
847 return lcs.length.getUint; | |
848 case LF_PROCEDURE_16t: | |
849 case LF_METHODLIST_16t: | |
850 debug DbgIO.println("unmangled procedure or methodlist in complex type"); | |
851 return 0; | |
852 case LF_UNION_16t: | |
853 LeafUnion lu = cast(LeafUnion)typestring[0]; | |
854 return lu.length.getUint; | |
855 case LF_OEM_16t: | |
856 LeafDynArray lda = cast(LeafDynArray)typestring[0]; | |
857 if ( lda !is null ) | |
858 return size_t.sizeof*2; | |
859 LeafAssocArray laa = cast(LeafAssocArray)typestring[0]; | |
860 if ( laa !is null ) | |
861 return size_t.sizeof; | |
862 LeafDelegate ld = cast(LeafDelegate)typestring[0]; | |
863 if ( ld !is null ) | |
864 return size_t.sizeof*2; | |
865 assert(0); | |
866 | |
867 default: | |
868 DbgIO.println("sizeofCV: unsupported complex type leaf 0x%x", typestring[0].leaf_index); | |
869 typestring = typestring[1..$]; | |
870 } | |
871 } | |
872 return 0; | |
873 } | |
874 | |
875 switch ( cvtype ) | |
876 { | |
877 case T_NOTYPE: | |
878 return 0; | |
879 case T_VOID: | |
880 case T_CHAR: | |
881 case T_UCHAR: | |
882 case T_RCHAR: | |
883 case T_BOOL08: | |
884 return 1; | |
885 case T_SHORT: case T_INT2: | |
886 case T_USHORT: case T_UINT2: | |
887 case T_WCHAR: | |
888 return 2; | |
889 case T_PVOID: case T_PFVOID: case T_PHVOID: case T_32PVOID: case T_32PFVOID: | |
890 case T_DCHAR: case T_32PDCHAR: case T_32PFDCHAR: | |
891 case T_PFCHAR: case T_PHCHAR: case T_32PCHAR: case T_32PFCHAR: case T_PCHAR: | |
892 case T_PFUCHAR: case T_PHUCHAR: case T_32PUCHAR: case T_32PFUCHAR: case T_PUCHAR: | |
893 case T_PRCHAR: case T_PFRCHAR: case T_PHRCHAR: case T_32PRCHAR: case T_32PFRCHAR: | |
894 case T_PWCHAR: case T_PFWCHAR: case T_PHWCHAR: case T_32PWCHAR: case T_32PFWCHAR: | |
895 case T_PINT2: case T_PSHORT: case T_32PSHORT: | |
896 case T_PUSHORT: case T_PUINT2: case T_32PUSHORT: | |
897 case T_32PBOOL08: case T_32PFBOOL08: | |
898 case T_INT4: | |
899 case T_UINT4: | |
900 case T_32PINT4: case T_PINT4: | |
901 case T_32PUINT4: case T_PUINT4: | |
902 case T_32PQUAD: case T_PQUAD: | |
903 case T_32PUQUAD: case T_PUQUAD: | |
904 case T_ULONG: | |
905 case T_REAL32: | |
906 case T_32PREAL32: case T_PREAL32: | |
907 case T_32PREAL64: case T_PREAL64: | |
908 case T_PREAL80: case T_PFREAL80: case T_PHREAL80: case T_32PREAL80: case T_32PFREAL80: | |
909 case T_CPLX32: | |
910 case T_32PCPLX32: case T_32PFCPLX32: | |
911 case T_32PCPLX64: case T_32PFCPLX64: | |
912 case T_32PCPLX80: case T_32PFCPLX80: | |
913 return 4; | |
914 case T_QUAD: | |
915 case T_UQUAD: | |
916 case T_REAL64: | |
917 case T_CPLX64: | |
918 return 8; | |
919 case T_CPLX80: | |
920 case T_REAL80: | |
921 return 10; | |
922 default: | |
923 debug DbgIO.println("sizeofCV: unknown codeview type 0x%x", cvtype); | |
924 } | |
925 return 0; | |
926 } | |
927 } |