Mercurial > projects > ddbg_continued
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/codeview/parser.d Tue Apr 05 20:44:01 2011 +0200 @@ -0,0 +1,862 @@ +/* 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); + } + } + } +}