// This file is distributed under a BSD license. See LICENSE.txt for details. #include "_types.hpp" #include "mapfile.hpp" #include // HACK: report buffer is 1mb fixed size /****************************************************************************/ void DebugInfo::Init() { Strings.Init(); StringData.Init(); Symbols.Init(); Files.Init(); NameSps.Init(); BaseAddress = 0; } void DebugInfo::Exit() { NameSps.Exit(); Files.Exit(); Symbols.Exit(); StringData.Exit(); Strings.Exit(); } sInt DebugInfo::MakeString(sChar *string) { // TODO: write a better implementation using hashing sInt i; for(i=0;iName.String = &StringData[sym->Name.Index]; sym->MangledName.String = &StringData[sym->MangledName.Index]; } for(sInt i=0;iVA; sU32 newSize = in->Size; if(oldVA != 0) { sInt adjust = newVA - oldVA; if(adjust < 0) // we have to shorten { newVA = oldVA; if(newSize >= (sU32) -adjust) newSize += adjust; } } if(newSize || in->Class == DIC_END) { DISymbol *out = Symbols.Add(); *out = *in; out->VA = newVA; out->Size = newSize; oldVA = newVA + newSize; oldSize = newSize; oldName = in->Name.String; } } delete[] syms; } void DebugInfo::Rebase(sU32 newBase) { sU32 delta = newBase - BaseAddress; for(sInt i=0;iName.Index = name; file->PackedSize = 0; file->Size = 0; return Files.Count - 1; } sInt DebugInfo::GetFileByName(sChar *name) { sChar *p; // skip path seperators while((p = (sChar *) sFindString(name,"\\"))) name = p + 1; while((p = (sChar *) sFindString(name,"/"))) name = p + 1; return GetFile(MakeString(name)); } sInt DebugInfo::GetNameSpace(sInt name) { for(sInt i=0;iName.Index = name; namesp->PackedSize = 0; namesp->Size = 0; return NameSps.Count - 1; } sInt DebugInfo::GetNameSpaceByName(sChar *name) { sChar *pp = name - 2; sChar *p; sInt cname; while((p = (sChar *) sFindString(pp+2,"::"))) pp = p; while((p = (sChar *) sFindString(pp+1,"."))) pp = p; if(pp != name - 2) { sChar buffer[2048]; sCopyString(buffer,name,2048); if(pp - name < 2048) buffer[pp - name] = 0; cname = MakeString(buffer); } else cname = MakeString(""); return GetNameSpace(cname); } void DebugInfo::StartAnalyze(sU32 startAddress,ReorderBuffer *reorder) { sInt i; Address = startAddress; Reorder = reorder; Reorder->Finish(); for(i=0;iAddress; // find out whether there is a remapping for the current address range if(info->Reorder) { if(!info->Reorder->Find(addr,&reord)) // no match { if(reord) len = sMin(availSize,reord->NewVA - addr); else len = availSize; info->Address += len; leftSize -= len; } else { len = sMin(availSize,reord->NewVA + reord->NewSize - addr); info->Address += len; leftSize -= len; // just a crude approximation here, gotta fix it somehow availSize = reord->OldSize * len / reord->NewSize; addr = reord->OldVA + (reord->OldSize * (addr - reord->NewVA) + reord->NewSize/2) / reord->NewSize; } } else { info->Address += availSize; leftSize -= availSize; } // try to find symbol for current address while(availSize) { if(!info->FindSymbol(addr,&sym)) // no match { if(sym) // skip to next symbol or everything if there's no next symbol len = sMin(availSize,sym->VA - addr); else len = availSize; addr += len; availSize -= len; } else // match with symbol { len = sMin(availSize,sym->VA + sym->Size - addr); addr += len; availSize -= len; sym->PackedSize += compSize * 0.125f * len / uncompSize; } } } } void DebugInfo::FinishAnalyze() { sInt i; for(i=0;i= Symbols[x].VA + Symbols[x].Size) l = x + 1; // continue in left half else { *sym = &Symbols[x]; // we found a match return sTRUE; } } *sym = (l + 1 < Symbols.Count) ? &Symbols[l+1] : 0; return sFALSE; } static sChar ReportBuffer[1024*1024]; bool symPackedSizeComp(const DISymbol &a,const DISymbol &b) { return a.PackedSize > b.PackedSize; } bool namePackedSizeComp(const DISymNameSp &a,const DISymNameSp &b) { return a.PackedSize > b.PackedSize; } bool filePackedSizeComp(const DISymFile &a,const DISymFile &b) { return a.PackedSize > b.PackedSize; } sChar *DebugInfo::WriteReport() { sChar *Report; sInt i,j; sU32 size; sF32 pSize; Report = ReportBuffer; sSPrintF(Report,512,"kkrunchy >> pack ratio report\n\n"); Report += sGetStringLen(Report); sSPrintF(Report,512,"Functions by packed size:\n"); Report += sGetStringLen(Report); std::sort(&Symbols[0],&Symbols[Symbols.Count],symPackedSizeComp); for(i=0;i0;j--) { sInt f1 = Symbols[j].FileNum; sInt f2 = Symbols[j-1].FileNum; if(f1 == -1 || f2 != -1 && sCmpStringI(Files[f1].Name.String,Files[f2].Name.String) < 0) sSwap(Symbols[j],Symbols[j-1]); } for(i=0;iNewVA = newVA; item->NewSize = newSize; item->OldVA = oldVA; item->OldSize = oldSize; } static bool reorderComp(const ReorderItem &a,const ReorderItem &b) { return a.NewVA < b.NewVA; } void ReorderBuffer::Finish() { // sort by new start address // (these are *lots* of records, so use a decent sort) std::sort(&Reorder[0],&Reorder[Reorder.Count],reorderComp); // just to be sure, assert we have no overlaps for(sInt i=0;i= Reorder[x].NewVA + Reorder[x].NewSize) l = x + 1; // continue in right half else { *reord = &Reorder[x]; // we got a match return sTRUE; } } *reord = (l + 1 < Reorder.Count) ? &Reorder[l + 1] : 0; return sFALSE; } /****************************************************************************/