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 }