// This file is distributed under a BSD license. See LICENSE.txt for details. #include "_types.hpp" #include "mapfile.hpp" #include "debuginfo.hpp" #include "_start.hpp" #include typedef sU32 (__stdcall *PUnDecorateSymbolName)(sChar *name,sChar *buffer,sInt bufferLen,sU32 flasgs); extern "C" void * __stdcall LoadLibraryA(sChar *name); extern "C" void * __stdcall GetProcAddress(void *module,sChar *name); // HACK: report buffer is 1mb fixed size /****************************************************************************/ struct MAPFileReader::Section { sInt Num; sU32 Start; sU32 Length; DIString Name; sBool Seen; sInt Class; }; sInt MAPFileReader::ScanString(sChar *&string,DebugInfo &to) { sChar buffer[3072]; sInt i; i = 0; while(*string && *string!=' ' && *string!='\r' && *string!='\n' && i<3071) buffer[i++] = *string++; buffer[i++] = 0; return to.MakeString(buffer); } sBool MAPFileReader::IsHexString(const sChar *str,sInt count) { while(count--) { if(!(*str>='0' && *str<='9' || *str>='A' && *str<='F' || *str>='a' && *str<='f')) return sFALSE; str++; } return sTRUE; } MAPFileReader::Section *MAPFileReader::GetSection(sInt num,sU32 offs) { sInt i; for(i=0;i=Sections[i].Start && offs=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;isymStart;j--) if(to.Symbols[j].VAClass!=DIC_END) { sVERIFY(i != to.Symbols.Count-1); sym->Size = sym[1].VA - sym->VA; } } // cleanup Sections.Exit(); delete[] text; return sTRUE; } /****************************************************************************/