sBool MAPFileReader::ReadDebugInfo(sChar *fileName,DebugInfo &to) { PUnDecorateSymbolName UnDecorateSymbolName = 0; // determine map file name sChar fileBuf[260]; sChar *text; sInt i; sCopyString(fileBuf,fileName,256); for(i=sGetStringLen(fileBuf)-1;i>=0 && fileBuf[i] != '.';i--); if(i > 0) sCopyString(fileBuf + i,".map",260-i); else sAppendString(fileBuf,".map",260); text = (sChar *) sSystem->LoadFile(fileBuf); if(!text) return sFALSE; // load dbghelp.dll to resolve symbol names if available void *module = LoadLibraryA("dbghelp.dll"); if(module) UnDecorateSymbolName = (PUnDecorateSymbolName) GetProcAddress(module,"UnDecorateSymbolName"); // actual reading code sChar *line,buffer[2048]; sInt j,code,data; sInt snum,offs,type,name,VA,fname; sInt symStart = to.Symbols.Count; Section *sec; DISymbol *sym; Sections.Init(); code = to.MakeString("CODE"); data = to.MakeString("DATA"); while(*text) { // find end of line line = text; while(*text && *text != '\n') text++; if(text[-1] == '\r' && text[0] == '\n') text[-1] = 0; if(*text) *text++ = 0; // parse this line of text if(line[0]==' ' && IsHexString(line+1,4) && line[5]==':' && IsHexString(line+6,8) && line[14]==' ') { if(IsHexString(line+15,8)) // section definition { sec = Sections.Add(); line += 1; sec->Num = sScanHex(line); line += 1; sec->Start = sScanHex(line); line += 1; sec->Length = sScanHex(line); line += 2; sec->Name.Index = ScanString(line,to); sScanSpace(line); type = ScanString(line,to); if(type == code) sec->Class = DIC_CODE; else if(type == data) sec->Class = DIC_DATA; else sec->Class = DIC_UNKNOWN; sec->Seen = sFALSE; } else // assume name definition { line += 1; snum = sScanHex(line); line += 1; offs = sScanHex(line); sec = GetSection(snum,offs); if(sec) { sScanSpace(line); name = ScanString(line,to); sScanSpace(line); VA = sScanHex(line); line += 5; fname = ScanString(line,to); if(!sec->Seen) { sym = to.Symbols.Add(); sSPrintF(buffer,2048,"__end%s",to.GetStringPrep(sec->Name.Index)); sym->Name.Index = to.MakeString(buffer); sym->FileNum = -1; sym->VA = VA-offs+sec->Start+sec->Length; sym->Size = 0; sym->Class = DIC_END; sec->Seen = sTRUE; } if(UnDecorateSymbolName) UnDecorateSymbolName(to.GetStringPrep(name),buffer,2048,0x1800); else sCopyString(buffer,to.GetStringPrep(name),2048); // add symbol sym = to.Symbols.Add(); sym->Name.Index = to.MakeString(buffer); sym->MangledName.Index = name; sym->FileNum = to.GetFile(fname); sym->VA = VA; sym->Size = 0; sym->Class = sec->Class; sym->NameSpNum = to.GetNameSpaceByName(buffer); } } } else if(!sCmpMem(line," Preferred load address is ",28) && IsHexString(line+28,8)) { line += 28; sU32 base = sScanHex(line); to.SetBaseAddress(base); } } // sort symbols by virtual address for(i=symStart+1;i<to.Symbols.Count;i++) for(j=i;j>symStart;j--) if(to.Symbols[j].VA<to.Symbols[j-1].VA) sSwap(to.Symbols[j],to.Symbols[j-1]); // calc sizes for(i=symStart;i<to.Symbols.Count;i++) { sym = &to.Symbols[i]; if(sym->Class!=DIC_END) { sVERIFY(i != to.Symbols.Count-1); sym->Size = sym[1].VA - sym->VA; } } // cleanup Sections.Exit(); delete[] text; return sTRUE; }
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to) { DWORD section,offset,rva; enum SymTagEnum tag; ULONGLONG length = 0; sU32 compilandId; IDiaSymbol *compiland = 0; BSTR name = 0, sourceName = 0; sBool codeFlag; symbol->get_symTag((DWORD *) &tag); symbol->get_relativeVirtualAddress(&rva); symbol->get_length(&length); symbol->get_addressSection(§ion); symbol->get_addressOffset(&offset); // is the previous symbol desperately looking for a length? we can help! if(DanglingLengthStart) { to.Symbols[to.Symbols.Count - 1].Size = rva - DanglingLengthStart; DanglingLengthStart = 0; } // get length from type for data if(tag == SymTagData) { IDiaSymbol *type; if(symbol->get_type(&type) == S_OK) { type->get_length(&length); type->Release(); } // if length still zero, just guess and take number of bytes between // this symbol and the next one. if(!length) DanglingLengthStart = rva; } compilandId = CompilandFromSectionOffset(section,offset,codeFlag); Session->symbolById(compilandId,&compiland); if(compiland) compiland->get_name(&sourceName); symbol->get_name(&name); // fill out structure sChar *nameStr = BStrToString(name,"<no name>"); sChar *sourceStr = BStrToString(sourceName,"<no source>"); if(tag == SymTagPublicSymbol) { length = 0; DanglingLengthStart = rva; } DISymbol *outSym = to.Symbols.Add(); outSym->Name.Index = outSym->MangledName.Index = to.MakeString(nameStr); outSym->FileNum = to.GetFileByName(sourceStr); outSym->VA = rva; outSym->Size = (sU32) length; outSym->Class = codeFlag ? DIC_CODE : DIC_DATA; outSym->NameSpNum = to.GetNameSpaceByName(nameStr); // clean up delete[] nameStr; delete[] sourceStr; if(compiland) compiland->Release(); if(sourceName) SysFreeString(sourceName); if(name) SysFreeString(name); }
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to) { // print a dot for each 1000 symbols processed static int counter = 0; ++counter; if( counter == 1000 ) { fputc( '.', stderr ); counter = 0; } DWORD section,offset,rva; enum SymTagEnum tag; ULONGLONG length = 0; BSTR name = 0, srcFileName = 0; symbol->get_symTag((DWORD *) &tag); symbol->get_relativeVirtualAddress(&rva); symbol->get_length(&length); symbol->get_addressSection(§ion); symbol->get_addressOffset(&offset); // get length from type for data if( tag == SymTagData ) { IDiaSymbol *type = NULL; if( symbol->get_type(&type) == S_OK ) // no SUCCEEDED test as may return S_FALSE! { if( FAILED(type->get_length(&length)) ) length = 0; type->Release(); } else length = 0; } const SectionContrib *contrib = ContribFromSectionOffset(section,offset); sInt objFile = 0; sInt sectionType = DIC_UNKNOWN; if(contrib) { objFile = contrib->ObjFile; sectionType = contrib->Type; } symbol->get_name(&name); // fill out structure sChar *nameStr = BStrToString( name, "<noname>", true); to.Symbols.push_back( DISymbol() ); DISymbol *outSym = &to.Symbols.back(); outSym->name = outSym->mangledName = to.MakeString(nameStr); outSym->objFileNum = objFile; outSym->VA = rva; outSym->Size = (sU32) length; outSym->Class = sectionType; outSym->NameSpNum = to.GetNameSpaceByName(nameStr); // clean up delete[] nameStr; if(name) SysFreeString(name); }