Improve performance of ScanForFunctions().

Mostly affects games with a lot of modules and exports.
This commit is contained in:
Unknown W. Brackets 2013-07-06 16:58:17 -07:00
parent b9c2e21105
commit 0ca8f5c655
3 changed files with 51 additions and 3 deletions

View File

@ -112,6 +112,7 @@ void SymbolMap::ResetSymbolMap()
#endif
entries.clear();
uniqueEntries.clear();
entryRanges.clear();
}
@ -127,6 +128,7 @@ void SymbolMap::AddSymbol(const char *symbolname, unsigned int vaddress, size_t
{
entries.push_back(e);
uniqueEntries.insert((const MapEntryUniqueInfo)e);
entryRanges[e.vaddress + e.size] = e.vaddress;
}
}
@ -193,6 +195,7 @@ bool SymbolMap::LoadSymbolMap(const char *filename)
e.UndecorateName();
entries.push_back(e);
uniqueEntries.insert((const MapEntryUniqueInfo)e);
entryRanges[e.vaddress + e.size] = e.vaddress;
}
}
fclose(f);
@ -238,6 +241,41 @@ int SymbolMap::GetSymbolNum(unsigned int address, SymbolType symmask) const
return -1;
}
bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) const
{
// entryRanges is indexed by end. The first entry after address should contain address.
// Otherwise, we have no entry that contains it, unless things overlap (which they shouldn't.)
const auto containingEntry = entryRanges.upper_bound(address);
if (containingEntry == entryRanges.end())
return false;
// The next most common case is a single symbol by start address.
// So we optimize for that by looking in our uniqueEntry set.
u32 start_address = containingEntry->second;
if (start_address <= address)
{
const MapEntryUniqueInfo searchKey = {start_address, start_address};
const auto entry = uniqueEntries.find(searchKey);
if (entry != uniqueEntries.end() && (entry->type & symmask) != 0)
{
info->address = entry->vaddress;
info->size = entry->size;
return true;
}
}
// Fall back to a slower scan.
int n = GetSymbolNum(address, symmask);
if (n != -1)
{
info->address = GetSymbolAddr(n);
info->size = GetSymbolSize(n);
return true;
}
return false;
}
const char* SymbolMap::getDirectSymbol(u32 address)
{
for (auto it = entries.begin(), end = entries.end(); it != end; ++it)
@ -572,6 +610,7 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress)
addr+=sig->size-4; //don't need to check function interior
entries.push_back(e);
uniqueEntries.insert((const MapEntryUniqueInfo)e);
entryRanges[e.vaddress + e.size] = e.vaddress;
break;
}
sig++;

View File

@ -20,6 +20,7 @@
#include "../../Globals.h"
#include <vector>
#include <set>
#include <map>
enum SymbolType
{
@ -27,6 +28,12 @@ enum SymbolType
ST_DATA=2
};
struct SymbolInfo
{
u32 address;
u32 size;
};
#ifdef _WIN32
struct HWND__;
typedef struct HWND__ *HWND;
@ -42,6 +49,7 @@ public:
void ResetSymbolMap();
void AnalyzeBackwards();
int GetSymbolNum(unsigned int address, SymbolType symmask=ST_FUNCTION) const;
bool GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask = ST_FUNCTION) const;
const char *GetDescription(unsigned int address) const;
#ifdef _WIN32
void FillSymbolListBox(HWND listbox, SymbolType symmask=ST_FUNCTION) const;
@ -96,6 +104,7 @@ private:
std::set<MapEntryUniqueInfo> uniqueEntries;
std::vector<MapEntry> entries;
std::map<u32, u32> entryRanges;
};
extern SymbolMap symbolMap;

View File

@ -351,10 +351,10 @@ namespace MIPSAnalyst
u32 addr;
for (addr = startAddr; addr<=endAddr; addr+=4)
{
int n = symbolMap.GetSymbolNum(addr,ST_FUNCTION);
if (n != -1)
SymbolInfo syminfo;
if (symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION))
{
addr = symbolMap.GetSymbolAddr(n) + symbolMap.GetSymbolSize(n);
addr = syminfo.address + syminfo.size;
continue;
}