Mercurial > projects > ddbg_continued
view 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 |
line wrap: on
line source
/* Ddbg - Win32 Debugger for the D programming language * Copyright (c) 2007 Jascha Wetzel * All rights reserved. See LICENSE.TXT for details. */ module codeview.parser; import codeview.codeview; import codeview.decl; import codeview.coff; import util; import container; import std.demangle; import std.string; class CodeViewException : Exception { this(string msg) { super(msg); } } class CodeViewParser { const uint cv_nb09_sig = intFromStr("NB09"); static: /********************************************************************************************** Parses the given CodeView section data from the given COFF image. **********************************************************************************************/ CodeView parse(COFFImage img, ubyte[] data) { if ( data.length <= 0 ) return null; CodeView cv = new CodeView; cv.image = img; cv.global_pub = new SymbolSet; cv.global_sym = new SymbolSet; cv.static_sym = new SymbolSet; DataReader dr = new DataReader(data); uint sig; dr.read(sig); if ( sig != cv_nb09_sig ) { char[4] sigstr; sigstr[] = (cast(char*)&sig)[0..4]; debug DbgIO.println("Unsupported CodeView version %s", sigstr); return null; } uint lfoDir; dr.read(lfoDir); dr.seek(lfoDir); ubyte[] buf; dr.readA(buf, DirHeader.sizeof); DirHeader* head = cast(DirHeader*)buf.ptr; assert(head.cbDirHeader==DirHeader.sizeof); assert(head.cbDirEntry==DirEntry.sizeof); DirEntry[] entries; dr.readA(entries, head.cDir); foreach ( DirEntry entry; entries ) { ubyte[] section_data; dr.seek(entry.lfo); dr.readA(section_data, entry.cb); switch ( entry.subsection ) { case sstModule: Module mod = parseModule(cv, section_data); assert ( entry.iMod-1 == cv.modulesByIndex.length ); cv.modulesByIndex ~= mod; cv.modulesByName[mod.name] = mod; debug(cvsections) DbgIO.println("sstModule section \"%s\"", mod.name); break; case sstAlignSym: debug(cvsections) DbgIO.println("sstAlignSym section"); assert ( entry.iMod <= cv.modulesByIndex.length ); Module mod = cv.modulesByIndex[entry.iMod-1]; parseSymbols(cv, section_data, mod.symbols, true, mod); break; case sstSrcModule: debug(cvsections) DbgIO.println("sstSrcModule section"); assert( entry.iMod <= cv.modulesByIndex.length ); parseSrcModule(cv, section_data, cv.modulesByIndex[entry.iMod-1]); break; case sstLibraries: debug(cvsections) DbgIO.println("sstLibraries section"); parseLibraries(cv, section_data); break; case sstGlobalSym: debug(cvsections) DbgIO.println("sstGlobalSym section"); parsePackedSymbols(cv, section_data, cv.global_sym); break; case sstGlobalPub: debug(cvsections) DbgIO.println("sstGlobalPub section"); parsePackedSymbols(cv, section_data, cv.global_pub); break; case sstStaticSym: debug(cvsections) DbgIO.println("sstStaticSym section"); parsePackedSymbols(cv, section_data, cv.static_sym); break; case sstGlobalTypes: debug(cvsections) DbgIO.println("sstGlobalTypes section"); parseGlobalTypes(cv, section_data, entry.lfo); break; case sstSegMap: debug(cvsections) DbgIO.println("sstSegMap section"); break; case sstSegName: debug(cvsections) DbgIO.println("sstSegName section"); break; case sstFileIndex: debug(cvsections) DbgIO.println("sstFileIndex section"); break; case sstSymbols: case sstTypes: case sstPublic: case sstPublicSym: case sstSrcLnSeg: case sstMPC: case sstPreComp: case sstPreCompMap: case sstOffsetMap16: case sstOffsetMap32: debug DbgIO.println("Unprocessed CV section 0x%x", entry.subsection); break; default: debug DbgIO.println("Unknown CV section 0x%x", entry.subsection); } } updateSymbols(cv, cv.global_pub.named_symbols); updateSymbols(cv, cv.global_sym.named_symbols); updateSymbols(cv, cv.static_sym.named_symbols); foreach ( m; cv.modulesByIndex ) updateSymbols(cv, m.symbols.named_symbols); cv.globalNamedSymbols = new AVLTree!(NamedSymbol); foreach ( ns; cv.global_sym.named_symbols ) cv.globalNamedSymbols.insert(ns); foreach ( ns; cv.global_pub.named_symbols ) cv.globalNamedSymbols.insert(ns); foreach ( ns; cv.static_sym.named_symbols ) cv.globalNamedSymbols.insert(ns); cv.updateCodeblocks(); return cv; } private: T min(T)(T a, T b) { return a<b?a:b; } /********************************************************************************************** Parse a Module from the given data. **********************************************************************************************/ Module parseModule(CodeView cv, ubyte[] data) { if ( data.length <= 0 ) throw new CodeViewException("parseModule on empty data"); DataReader dr = new DataReader(data); Module mod = new Module(cv); ubyte[] buf; dr.readA(buf, ModuleHeader.sizeof); mod.header = cast(ModuleHeader*)buf.ptr; assert(mod.header.Style==intFromStr("CV")); dr.readA!(SegInfo)(mod.seginfos, mod.header.cSeg); dr.read(mod.name); return mod; } /********************************************************************************************** **********************************************************************************************/ void parseSymbols(CodeView cv, ubyte[] data, SymbolSet symbols, bool skip_to_ssearch=false, Module mod=null) { if ( data.length <= 0 ) throw new CodeViewException("parseSymbols on empty data"); DataReader dr = new DataReader(data); uint num_sym; // skip until S_SSEARCH symbol is found while ( skip_to_ssearch && dr.available ) { ushort length, index; dr.read(length); dr.read(index); if ( index == SymbolIndex.S_SSEARCH ) { dr.relseek(-4); break; } } uint sym_off; bool expecting_arguments=false; ScopeSymbol[uint] scope_syms; ScopeSymbol parent_scope; while ( dr.available ) { ushort length, index; uint next_symbol, symbol_start; void addSymbol(Symbol sym) { assert( !expecting_arguments || parent_scope !is null ); if ( parent_scope !is null ) { if ( expecting_arguments ) (cast(ProcedureSymbol)parent_scope).arguments.add(sym); else parent_scope.symbols.add(sym); } else symbols.add(sym); } symbol_start = dr.cursor; dr.read(length); next_symbol = dr.cursor+length; if ( next_symbol > dr.data.length ) { debug DbgIO.println("WARNING: length %d for symbol exceeds block size %d - skipping section", length, dr.data.length); if ( mod !is null ) debug DbgIO.println("in module %s", mod.name); return; } dr.read(index); ubyte[] buf; switch ( index ) { case SymbolIndex.S_COMPILE: ubyte machine, language; ushort flags; dr.read(machine); dr.read(language); dr.read(flags); string version_string; dr.read(version_string); debug(cvsymbols) DbgIO.println("machine: 0x%x, language: %d, flags: 0x%x, version: %s", machine, language, flags, version_string); break; case SymbolIndex.S_SSEARCH: dr.read(sym_off); ushort pe_section; dr.read(pe_section); if ( mod !is null ) mod.pe_section = pe_section; break; case SymbolIndex.S_END: debug(cvsymbols) DbgIO.println("S_END"); if ( parent_scope !is null ) { if ( parent_scope.parent_scope !is null ) parent_scope = parent_scope.parent_scope; else parent_scope = null; } else { debug DbgIO.println("S_END with no active parent scope"); } expecting_arguments = false; break; case SymbolIndex.S_ENDARG: expecting_arguments = false; break; case SymbolIndex.S_RETURN: dr.readA(buf, CVReturnSymbol.sizeof); ReturnSymbol rsym = new ReturnSymbol(cast(CVReturnSymbol*)buf.ptr); if ( rsym.cvdata.style == 1 ) { ubyte count; dr.read(count); dr.readA!(ubyte)(rsym.registers, count); } ProcedureSymbol psym = cast(ProcedureSymbol)parent_scope; assert(psym !is null); psym.return_sym = rsym; break; case SymbolIndex.S_LPROC32: case SymbolIndex.S_GPROC32: dr.readA(buf, CVProcedureSymbol.sizeof); ProcedureSymbol psym = new ProcedureSymbol(cast(SymbolIndex)index, symbol_start, cast(CVProcedureSymbol*)buf.ptr); dr.read(psym.mangled_name); psym.name_notype = demangleName(psym.mangled_name); psym.name_type = demangle(psym.mangled_name); debug(cvsymbols) DbgIO.println("PROC32 %s (%s) s:%x o:%x", psym.name_type, psym.name_notype, psym.cvdata.segment, psym.cvdata.offset); scope_syms[symbol_start] = psym; addSymbol(psym); assert ( parent_scope is null || psym.cvdata.pParent==parent_scope.lfo ); if ( psym.cvdata.pParent in scope_syms ) { psym.parent_scope = scope_syms[psym.cvdata.pParent]; psym.parent_scope.symbols.add(psym); } parent_scope = psym; expecting_arguments = true; break; case SymbolIndex.S_BPREL32: dr.readA(buf, CVStackSymbol.sizeof); StackSymbol stsym = new StackSymbol(cast(CVStackSymbol*)buf.ptr); dr.read(stsym.mangled_name); stsym.name_notype = demangleName(stsym.mangled_name); stsym.name_type = demangle(stsym.mangled_name); debug(cvsymbols) DbgIO.println( "BPREL32 %s%s [%s] 0x%x o:%d", parent_scope !is null?"("~parent_scope.name_type~") ":"", stsym.name_type, stsym.name_notype, stsym.cvtype, cast(int)stsym.cvdata.offset ); addSymbol(stsym); break; case SymbolIndex.S_LDATA32: case SymbolIndex.S_GDATA32: case SymbolIndex.S_PUB32: dr.readA(buf, CVDataSymbol.sizeof); DataSymbol dsym = new DataSymbol(cast(SymbolIndex)index, cast(CVDataSymbol*)buf.ptr); dr.read(dsym.mangled_name); dsym.name_notype = demangleName(dsym.mangled_name); dsym.name_type = demangle(dsym.mangled_name); 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); addSymbol(dsym); break; case SymbolIndex.S_ALIGN: debug(cvsymbols) DbgIO.println("ALIGN"); break; case SymbolIndex.S_UDT: UserDefinedType udt = new UserDefinedType; dr.read(udt.type_index); dr.read(udt.name); cv.udtypes ~= udt; break; case SymbolIndex.S_PROCREF: case SymbolIndex.S_DATAREF: break; case SymbolIndex.S_REGISTER: case SymbolIndex.S_CONSTANT: case SymbolIndex.S_SKIP: case SymbolIndex.S_CVRESERVE: case SymbolIndex.S_OBJNAME: case SymbolIndex.S_COBOLUDT: case SymbolIndex.S_MANYREG: case SymbolIndex.S_ENTRYTHIS: case SymbolIndex.S_BPREL16: case SymbolIndex.S_LDATA16: case SymbolIndex.S_PUB16: case SymbolIndex.S_LPROC16: case SymbolIndex.S_GPROC16: case SymbolIndex.S_THUNK16: case SymbolIndex.S_BLOCK16: case SymbolIndex.S_WITH16: case SymbolIndex.S_LABEL16: case SymbolIndex.S_CEXMODEL16: case SymbolIndex.S_VFTPATH16: case SymbolIndex.S_REGREL16: case SymbolIndex.S_GDATA16: case SymbolIndex.S_THUNK32: case SymbolIndex.S_BLOCK32: case SymbolIndex.S_WITH32: case SymbolIndex.S_LABEL32: case SymbolIndex.S_CEXMODEL32: case SymbolIndex.S_VFTPATH32: case SymbolIndex.S_REGREL32: case SymbolIndex.S_LTHREAD32: case SymbolIndex.S_GTHREAD32: debug DbgIO.println("unprocessed symbol index 0x%x", index); break; default: debug DbgIO.println("unknown symbol index 0x%x", index); } dr.seek(next_symbol); } } /********************************************************************************************** **********************************************************************************************/ void parseSrcModule(CodeView cv, ubyte[] data, Module mod) { if ( data.length <= 0 ) throw new CodeViewException("parseSrcModule on empty data"); DataReader dr = new DataReader(data); ushort cFile, cSeg; dr.read(cFile); dr.read(cSeg); SourceModule smod = new SourceModule; mod.source_module = smod; cv.source_modules ~= smod; uint[] baseSrcFile, start_end; ushort[] seginds; dr.readA(baseSrcFile, cast(uint)cFile); dr.readA(start_end, cast(uint)cSeg*2); dr.readA(seginds, cast(uint)cSeg); debug(cvparser) DbgIO.println("Module %s files=%d segs=%d", mod.name, cFile, cSeg); foreach ( fileoffset; baseSrcFile ) { dr.seek(fileoffset); dr.read(cSeg); ushort pad; dr.read(pad); SourceFile file = new SourceFile; file.source_module = smod; uint[] baseSrcLn; dr.readA(baseSrcLn, cast(uint)cSeg); start_end = null; dr.readA(start_end, cast(uint)cSeg*2); dr.read(file.name); debug(cvparser) DbgIO.println("\tFile %s segs=%d", file.name, cSeg); smod.files ~= file; foreach ( int i, segoff; baseSrcLn ) { dr.seek(segoff); SourceSegment seg = new SourceSegment; file.segments ~= seg; seg.file = file; seg.start = start_end[i*2]; seg.end = start_end[i*2+1]; dr.read(pad); // segment index ushort cPair; dr.read(cPair); debug(cvparser) DbgIO.println("\t\tSegment %d lines=%d", file.segments.length-1, cPair); uint[] offset; ushort[] linenumber; dr.readA(offset, cast(uint)cPair); dr.readA(linenumber, cast(uint)cPair); foreach ( int j, l; linenumber ) { CodeBlock cb = new CodeBlock(offset[j], l, seg); file.blocks_by_line[l] ~= cb; debug(cvparser) { bool inserted = cv.codeblocks.insert(cb); if ( !inserted ) DbgIO.println("failed to insert block %s, already exists", cb); } else cv.codeblocks.insert(cb); } } file.lines = file.blocks_by_line.keys.dup.sort; } } /********************************************************************************************** **********************************************************************************************/ void parseLibraries(CodeView cv, ubyte[] data) { if ( data.length <= 0 ) throw new CodeViewException("parseLibraries on empty data"); DataReader dr = new DataReader(data); while ( dr.available ) { string lib; dr.read(lib); cv.libraries ~= lib; } } /********************************************************************************************** **********************************************************************************************/ void parsePackedSymbols(CodeView cv, ubyte[] data, SymbolSet symbols) { if ( data.length <= 0 ) throw new CodeViewException("parsePackedSymbols on empty data"); DataReader dr = new DataReader(data); ubyte[] buf; dr.readA(buf, PackedSymbolsHeader.sizeof); PackedSymbolsHeader* gsh = cast(PackedSymbolsHeader*)buf.ptr; dr.readA(buf, gsh.cbSymbol); parseSymbols(cv, buf, symbols); } /********************************************************************************************** **********************************************************************************************/ void parseGlobalTypes(CodeView cv, ubyte[] data, uint absolute_offset) { DataReader dr = new DataReader(data); uint flags, cType; uint[] offType; dr.read(flags); dr.read(cType); dr.readA(offType, cType); uint base = dr.cursor; foreach ( off; offType ) { dr.seek(base+off); ushort len; dr.read(len); ubyte[] buf; dr.readA(buf, cast(uint)len); cv.type_strings ~= parseTypeString(cv, buf); } } /********************************************************************************************** **********************************************************************************************/ Leaf[] parseTypeString(CodeView cv, ubyte[] data) { debug(cvdump) foreach ( b; data ) DbgIO.print("%02x ", b); debug(cvdump) DbgIO.println(""); DataReader dr = new DataReader(data); Leaf[] leafs; bool first = true; while ( dr.available ) { ushort leaf_index; dr.read(leaf_index); Leaf l; // debug(cvparser) DbgIO.println("parsing 0x%x", leaf_index); switch ( leaf_index ) { case LF_MODIFIER_16t: LeafModifer lm = new LeafModifer; l = lm; dr.read(lm.attribute); dr.read(lm.index); break; case LF_POINTER_16t: LeafPointer lp = new LeafPointer; l = lp; dr.read(lp.attribute); dr.read(lp.type); switch ( lp.attribute&0x1f ) { case 0: case 10: break; default: debug DbgIO.println("unprocessed pointer type: 0x%x", lp.attribute); assert(0); } break; case LF_ARRAY_16t: LeafArray la = new LeafArray; l = la; dr.read(la.elemtype); dr.read(la.idxtype); la.length = parseNumericLeaf(dr); dr.read(la.name); debug(cvparser) DbgIO.println("LF_ARRAY: %d 0x%x", la.length.getUint, 0x1000+cv.type_strings.length); break; case LF_PROCEDURE_16t: LeafProcedure lp = new LeafProcedure; l = lp; dr.read(lp.rvtype); dr.read(lp.call); dr.read(lp.reserved); dr.read(lp.cParms); dr.read(lp.arglist); break; case LF_MFUNCTION_16t: LeafMFunction lmf = new LeafMFunction; l = lmf; dr.read(lmf.rvtype); dr.read(lmf._class); dr.read(lmf._this); dr.read(lmf.call); dr.read(lmf.reserved); dr.read(lmf.cParms); dr.read(lmf.arglist); dr.read(lmf.thisadjust); break; case LF_VTSHAPE: LeafVTShape lvts = new LeafVTShape; l = lvts; ushort count; dr.read(count); dr.readA(lvts.descriptor, cast(uint)(count+1)>>1); // skip rest of typestring dr.seek(dr.data.length); break; case LF_CLASS_16t: case LF_STRUCTURE_16t: LeafClassStruc lcs = new LeafClassStruc; l = lcs; dr.read(lcs.count); dr.read(lcs.field); dr.read(lcs.property); dr.read(lcs.dList); dr.read(lcs.vshape); lcs.length = parseNumericLeaf(dr); dr.read(lcs.name); lcs.type = cast(ushort)(0x1000+cv.type_strings.length); debug(cvparser) DbgIO.println( "%s 0x%x '%s' fl: 0x%x prop: 0x%x, length=0x%x", leaf_index==LF_CLASS_16t?"class":"struct", lcs.type, lcs.name, lcs.field, lcs.property, lcs.length.getUint ); cv.UDTsByName[lcs.name] = lcs; break; case LF_ENUM_16t: LeafEnum le = new LeafEnum; l = le; dr.read(le.count); dr.read(le.type); dr.read(le.field); dr.read(le.property); dr.read(le.name); debug(cvparser) DbgIO.println( "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 ); cv.UDTsByName[le.name] = le; break; case LF_UNION_16t: LeafUnion lu = new LeafUnion; l = lu; dr.read(lu.count); dr.read(lu.field); dr.read(lu.property); lu.length = parseNumericLeaf(dr); dr.read(lu.name); // skip rest of typestring dr.seek(dr.data.length); debug(cvparser) DbgIO.println("Union '%s' count %d fields 0x%x length 0x%x", lu.name, lu.count, lu.field, lu.length.getUint); cv.UDTsByName[lu.name] = lu; break; case LF_OEM_16t: ushort oem; dr.read(oem); assert(oem == OEM_DIGITALMARS); dr.read(oem); ushort count; dr.read(count); assert(count == 2); switch ( oem ) { case D_DYN_ARRAY: LeafDynArray lda = new LeafDynArray; l = lda; dr.read(lda.index_type); dr.read(lda.elem_type); debug(cvparser) DbgIO.println("Dynamic array index_type 0x%x elem_type 0x%x", lda.index_type, lda.elem_type); break; case D_ASSOC_ARRAY: LeafAssocArray laa = new LeafAssocArray; l = laa; dr.read(laa.key_type); dr.read(laa.elem_type); debug(cvparser) DbgIO.println("Associativ array key_type 0x%x elem_type 0x%x", laa.key_type, laa.elem_type); break; default: LeafDelegate ld = new LeafDelegate; l = ld; dr.read(ld.this_type); dr.read(ld.func_type); debug(cvparser) DbgIO.println("Delegate this_type 0x%x func_type 0x%x", ld.this_type, ld.func_type); break; } break; case LF_ARGLIST_16t: LeafArgList lal = new LeafArgList; l = lal; dr.read(lal.argcount); dr.readA(lal.indeces, cast(uint)lal.argcount); break; case LF_FIELDLIST_16t: debug(cvparser) DbgIO.println("fieldlist 0x%x", 0x1000+cv.type_strings.length); LeafFieldList lfl = new LeafFieldList; l = lfl; while ( dr.available ) lfl.fields ~= parseSubfield(dr); // skip rest of typestring dr.seek(dr.data.length); break; case LF_DERIVED_16t: LeafDerived ld = new LeafDerived; l = ld; ushort count; dr.read(count); dr.readA(ld.types, cast(uint)count); break; case LF_METHODLIST_16t: LeafMethodList lml = new LeafMethodList; l = lml; // skip rest of typestring dr.seek(dr.data.length); break; default: debug DbgIO.println("unprocessed leaf index 0x%x at 0x%x", leaf_index, dr.cursor-2); l = new Leaf; } assert ( l !is null ); l.leaf_index = leaf_index; leafs ~= l; } return leafs; } /********************************************************************************************** **********************************************************************************************/ Leaf parseSubfield(DataReader dr) { ushort leaf_index; dr.read(leaf_index); Leaf l; switch ( leaf_index ) { case LF_BCLASS_16t: LeafBaseClass lbc = new LeafBaseClass; l = lbc; dr.read(lbc.type); dr.read(lbc.attribute); lbc.offset = parseNumericLeaf(dr); debug(cvparser) DbgIO.println("SFbclass"); break; case LF_MEMBER_16t: LeafMember lm = new LeafMember; l = lm; dr.read(lm.type); dr.read(lm.attribute); lm.offset = parseNumericLeaf(dr); dr.read(lm.name); debug(cvparser) DbgIO.println("SFmember: %s", lm.name); break; case LF_METHOD_16t: LeafMethod lm = new LeafMethod; l = lm; dr.read(lm.count); dr.read(lm.mList); dr.read(lm.name); debug(cvparser) DbgIO.println("SFmethod: %d 0x%x %s", lm.count, lm.mList, lm.name); break; case LF_ENUMERATE: LeafEnumNameValue le = new LeafEnumNameValue; l = le; dr.read(le.attribute); le.value = parseNumericLeaf(dr); dr.read(le.name); debug(cvparser) DbgIO.println("SFenumerate: %s %d", le.name, le.value.getUint); break; case LF_NESTTYPE_16t: LeafNestedType ln = new LeafNestedType; l = ln; dr.read(ln.index); dr.read(ln.name); debug(cvparser) DbgIO.println("SFnesttype: %s", ln.name); break; case LF_STMEMBER_16t: LeafStaticDataMember ls = new LeafStaticDataMember; l = ls; dr.read(ls.type); dr.read(ls.attribute); dr.read(ls.name); debug(cvparser) DbgIO.println("SFstmember: %s", ls.name); break; case LF_SKIP_16t: dr.seek(dr.data.length); debug(cvparser) DbgIO.println("SFskip"); break; default: debug DbgIO.println("unprocessed subfield index 0x%x", leaf_index); l = new Leaf; } if ( dr.available ) { ubyte pad; dr.peek(pad); if ( pad > 0xf0 ) dr.relseek(pad&0xf); } assert ( l !is null ); l.leaf_index = leaf_index; return l; } /********************************************************************************************** **********************************************************************************************/ LeafNumeric parseNumericLeaf(DataReader dr) { LeafNumeric nl = new LeafNumeric; dr.read(nl.leaf_index); if ( nl.leaf_index < 0x8000 ) { nl.us = cast(ushort)nl.leaf_index; nl.leaf_index = LF_USHORT; } else switch ( nl.leaf_index ) { case LF_VARSTRING: dr.read(nl.str); break; case LF_CHAR: dr.read(nl.c); break; case LF_SHORT: dr.read(nl.s); break; case LF_USHORT: dr.read(nl.us); break; case LF_LONG: dr.read(nl.i); break; case LF_ULONG: dr.read(nl.ui); break; case LF_REAL32: dr.read(nl.f); break; case LF_REAL64: dr.read(nl.d); break; case LF_REAL80: dr.read(nl.r); break; case LF_QUADWORD: dr.read(nl.l); break; case LF_UQUADWORD: dr.read(nl.ul); break; case LF_COMPLEX32: dr.read(nl.cf); break; case LF_COMPLEX64: case LF_COMPLEX80: case LF_REAL48: case LF_COMPLEX128: case LF_REAL128: default: debug DbgIO.println("unknown leaftype %x", nl.leaf_index); } return nl; } /********************************************************************************************** Updates symbol size fields and mangled_names. Since both can only be determined fully after sstGlobalTypes have been read. **********************************************************************************************/ void updateSymbols(CodeView cv, NamedSymbol[] syms) { foreach ( s; syms ) { if ( s.mangled_name is null || s.mangled_name.length <= 0 ) s.mangled_name = cv.mangle(s); ScopeSymbol scs = cast(ScopeSymbol)s; if ( scs !is null ) updateSymbols(cv, scs.symbols.named_symbols); ProcedureSymbol ps = cast(ProcedureSymbol)s; if ( ps !is null ) updateSymbols(cv, ps.arguments.named_symbols); string type = cv.mangleType(s); if ( type is null ) continue; DataSymbol ds = cast(DataSymbol)s; if ( ds !is null ) ds.size = cv.sizeofCV(ds.cvdata.type); else { StackSymbol ss = cast(StackSymbol)s; if ( ss !is null ) ss.size = cv.sizeofCV(ss.cvdata.type); } } } }