mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-17 17:43:13 +00:00
Ok, part 2/2 of the symbol code rewrite. You can now create and use function signature files. A monkey ball signature file included. Now to add some cooler features...
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@294 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
23665a7b93
commit
c0c6fc9e6d
BIN
Binary/win32/Data/monkey.dsy
Normal file
BIN
Binary/win32/Data/monkey.dsy
Normal file
Binary file not shown.
@ -796,14 +796,6 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="PowerPC"
|
Name="PowerPC"
|
||||||
>
|
>
|
||||||
<File
|
|
||||||
RelativePath=".\Src\PowerPC\FunctionDB.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\Src\PowerPC\FunctionDB.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\PowerPC\Gekko.h"
|
RelativePath=".\Src\PowerPC\Gekko.h"
|
||||||
>
|
>
|
||||||
@ -844,6 +836,14 @@
|
|||||||
RelativePath=".\Src\PowerPC\SignatureDB.h"
|
RelativePath=".\Src\PowerPC\SignatureDB.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\PowerPC\SymbolDB.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\PowerPC\SymbolDB.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Interpreter"
|
Name="Interpreter"
|
||||||
>
|
>
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
#include "../VolumeHandler.h"
|
#include "../VolumeHandler.h"
|
||||||
#include "../PatchEngine.h"
|
#include "../PatchEngine.h"
|
||||||
#include "../PowerPC/SignatureDB.h"
|
#include "../PowerPC/SignatureDB.h"
|
||||||
#include "../PowerPC/FunctionDB.h"
|
#include "../PowerPC/SymbolDB.h"
|
||||||
|
|
||||||
#include "../MemTools.h"
|
#include "../MemTools.h"
|
||||||
#include "MappedFile.h"
|
#include "MappedFile.h"
|
||||||
@ -401,17 +401,16 @@ bool CBoot::LoadMapFromFilename(const std::string &_rFilename, const char *_game
|
|||||||
std::string strMapFilename = GenerateMapFilename();
|
std::string strMapFilename = GenerateMapFilename();
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!Debugger::LoadSymbolMap(strMapFilename.c_str()))
|
if (!g_symbolDB.LoadMap(strMapFilename.c_str()))
|
||||||
{
|
{
|
||||||
if (_gameID != NULL)
|
if (_gameID != NULL)
|
||||||
{
|
{
|
||||||
BuildCompleteFilename(strMapFilename, _T("maps"), std::string(_gameID) + _T(".map"));
|
BuildCompleteFilename(strMapFilename, _T("maps"), std::string(_gameID) + _T(".map"));
|
||||||
success = Debugger::LoadSymbolMap(strMapFilename.c_str());
|
success = g_symbolDB.LoadMap(strMapFilename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debugger::PushMapToFunctionDB(&g_funcDB);
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "../Debugger/Debugger_SymbolMap.h"
|
#include "../Debugger/Debugger_SymbolMap.h"
|
||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
|
#include "../PowerPC/SymbolDB.h"
|
||||||
#include "ElfReader.h"
|
#include "ElfReader.h"
|
||||||
|
|
||||||
void bswap(Elf32_Word &w) {w = Common::swap32(w);}
|
void bswap(Elf32_Word &w) {w = Common::swap32(w);}
|
||||||
@ -232,22 +233,20 @@ bool ElfReader::LoadSymbols()
|
|||||||
if (bRelocate)
|
if (bRelocate)
|
||||||
value += sectionAddrs[sectionIndex];
|
value += sectionAddrs[sectionIndex];
|
||||||
|
|
||||||
Debugger::ESymbolType symtype = Debugger::ST_DATA;
|
int symtype = Symbol::SYMBOL_DATA;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case STT_OBJECT:
|
case STT_OBJECT:
|
||||||
symtype = Debugger::ST_DATA; break;
|
symtype = Symbol::SYMBOL_DATA; break;
|
||||||
case STT_FUNC:
|
case STT_FUNC:
|
||||||
symtype =Debugger:: ST_FUNCTION; break;
|
symtype = Symbol::SYMBOL_FUNCTION; break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//host->AddSymbol(name, value, size, symtype);
|
g_symbolDB.AddKnownSymbol(value, size, name, symtype);
|
||||||
Debugger::AddSymbol(Debugger::Symbol(value, size, symtype, name));
|
|
||||||
|
|
||||||
hasSymbols = true;
|
hasSymbols = true;
|
||||||
//...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasSymbols;
|
return hasSymbols;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "CoreTiming.h"
|
#include "CoreTiming.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "PowerPC/Jit64/JitCache.h"
|
#include "PowerPC/Jit64/JitCache.h"
|
||||||
#include "PowerPC/FunctionDB.h"
|
#include "PowerPC/SymbolDB.h"
|
||||||
#include "PowerPCDisasm.h"
|
#include "PowerPCDisasm.h"
|
||||||
|
|
||||||
#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0)
|
#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0)
|
||||||
@ -93,7 +93,7 @@ void Console_Submit(const char *cmd)
|
|||||||
sscanf(cmd, "%s %08x", temp, &addr);
|
sscanf(cmd, "%s %08x", temp, &addr);
|
||||||
if (addr!=0)
|
if (addr!=0)
|
||||||
{
|
{
|
||||||
g_funcDB.PrintCalls(addr);
|
g_symbolDB.PrintCalls(addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -107,7 +107,7 @@ void Console_Submit(const char *cmd)
|
|||||||
sscanf(cmd, "%s %08x", temp, &addr);
|
sscanf(cmd, "%s %08x", temp, &addr);
|
||||||
if (addr!=0)
|
if (addr!=0)
|
||||||
{
|
{
|
||||||
g_funcDB.PrintCallers(addr);
|
g_symbolDB.PrintCallers(addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -167,7 +167,7 @@ void Console_Submit(const char *cmd)
|
|||||||
}
|
}
|
||||||
CASE("lisf")
|
CASE("lisf")
|
||||||
{
|
{
|
||||||
g_funcDB.List();
|
g_symbolDB.List();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("blach\n");
|
printf("blach\n");
|
||||||
|
@ -29,11 +29,9 @@
|
|||||||
#include "../HW/CPU.h"
|
#include "../HW/CPU.h"
|
||||||
#include "../Host.h"
|
#include "../Host.h"
|
||||||
|
|
||||||
#include "Debugger_SymbolMap.h"
|
#include "../PowerPC/SymbolDB.h"
|
||||||
#include "Debugger_BreakPoints.h"
|
#include "Debugger_BreakPoints.h"
|
||||||
|
|
||||||
using namespace Debugger;
|
|
||||||
|
|
||||||
CBreakPoints::TBreakPoints CBreakPoints::m_BreakPoints;
|
CBreakPoints::TBreakPoints CBreakPoints::m_BreakPoints;
|
||||||
CBreakPoints::TMemChecks CBreakPoints::m_MemChecks;
|
CBreakPoints::TMemChecks CBreakPoints::m_MemChecks;
|
||||||
u32 CBreakPoints::m_iBreakOnCount = 0;
|
u32 CBreakPoints::m_iBreakOnCount = 0;
|
||||||
@ -51,7 +49,7 @@ void TMemCheck::Action(u32 iValue, u32 addr, bool write, int size, u32 pc)
|
|||||||
{
|
{
|
||||||
LOG(MEMMAP,"CHK %08x %s%i at %08x (%s)",
|
LOG(MEMMAP,"CHK %08x %s%i at %08x (%s)",
|
||||||
iValue, write ? "Write" : "Read", size*8, addr,
|
iValue, write ? "Write" : "Read", size*8, addr,
|
||||||
Debugger::GetDescription(addr));
|
g_symbolDB.GetDescription(addr));
|
||||||
}
|
}
|
||||||
if (Break)
|
if (Break)
|
||||||
CCPU::Break();
|
CCPU::Break();
|
||||||
@ -154,14 +152,10 @@ void CBreakPoints::AddAutoBreakpoints()
|
|||||||
|
|
||||||
for (int i = 0; i < sizeof(bps) / sizeof(const char *); i++)
|
for (int i = 0; i < sizeof(bps) / sizeof(const char *); i++)
|
||||||
{
|
{
|
||||||
XSymbolIndex idx = FindSymbol(bps[i]);
|
Symbol *symbol = g_symbolDB.GetSymbolFromName(bps[i]);
|
||||||
if (idx != 0)
|
if (symbol)
|
||||||
{
|
AddBreakPoint(symbol->address, false);
|
||||||
const Symbol &symbol = GetSymbol(idx);
|
|
||||||
AddBreakPoint(symbol.vaddress, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Host_UpdateBreakPointView();
|
Host_UpdateBreakPointView();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,223 +22,12 @@
|
|||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
#include "../PowerPC/PowerPC.h"
|
#include "../PowerPC/PowerPC.h"
|
||||||
#include "../PowerPC/PPCAnalyst.h"
|
#include "../PowerPC/PPCAnalyst.h"
|
||||||
#include "../PowerPC/FunctionDB.h"
|
#include "../PowerPC/SymbolDB.h"
|
||||||
#include "../../../../Externals/Bochs_disasm/PowerPCDisasm.h"
|
#include "../../../../Externals/Bochs_disasm/PowerPCDisasm.h"
|
||||||
|
|
||||||
namespace Debugger
|
namespace Debugger
|
||||||
{
|
{
|
||||||
|
|
||||||
static XVectorSymbol g_Symbols;
|
|
||||||
|
|
||||||
Symbol::Symbol(u32 _Address, u32 _Size, ESymbolType _Type, const char *_rName) :
|
|
||||||
vaddress(_Address),
|
|
||||||
size(_Size),
|
|
||||||
runCount(0),
|
|
||||||
type(_Type),
|
|
||||||
m_strName(_rName)
|
|
||||||
{
|
|
||||||
// invalid entry
|
|
||||||
if (m_strName.size() < 2)
|
|
||||||
{
|
|
||||||
_Address = -1;
|
|
||||||
_Size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol::~Symbol()
|
|
||||||
{
|
|
||||||
m_vecBackwardLinks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
g_Symbols.clear();
|
|
||||||
|
|
||||||
// 0 is an invalid entry
|
|
||||||
Symbol Invalid(static_cast<u32>(-1), 0, ST_FUNCTION, "Invalid");
|
|
||||||
g_Symbols.push_back(Invalid);
|
|
||||||
}
|
|
||||||
|
|
||||||
XSymbolIndex AddSymbol(const Symbol& symbol)
|
|
||||||
{
|
|
||||||
XSymbolIndex old = FindSymbol(symbol.GetName().c_str());
|
|
||||||
if (old != 0)
|
|
||||||
return old;
|
|
||||||
g_Symbols.push_back(symbol);
|
|
||||||
return (XSymbolIndex)(g_Symbols.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Symbol& GetSymbol(XSymbolIndex _Index)
|
|
||||||
{
|
|
||||||
if (_Index < (XSymbolIndex)g_Symbols.size())
|
|
||||||
return g_Symbols[_Index];
|
|
||||||
|
|
||||||
PanicAlert("GetSymbol is called with an invalid index %i", _Index);
|
|
||||||
return g_Symbols[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const XVectorSymbol& AccessSymbols()
|
|
||||||
{
|
|
||||||
return g_Symbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol& AccessSymbol(XSymbolIndex _Index)
|
|
||||||
{
|
|
||||||
if (_Index < (XSymbolIndex)g_Symbols.size())
|
|
||||||
return g_Symbols[_Index];
|
|
||||||
|
|
||||||
PanicAlert("AccessSymbol is called with an invalid index %i", _Index);
|
|
||||||
return g_Symbols[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
XSymbolIndex FindSymbol(u32 _Address)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)g_Symbols.size(); i++)
|
|
||||||
{
|
|
||||||
const Symbol& rSymbol = g_Symbols[i];
|
|
||||||
if ((_Address >= rSymbol.vaddress) && (_Address < rSymbol.vaddress + rSymbol.size))
|
|
||||||
{
|
|
||||||
return (XSymbolIndex)i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid index
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSymbolIndex FindSymbol(const char *name)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)g_Symbols.size(); i++)
|
|
||||||
{
|
|
||||||
const Symbol& rSymbol = g_Symbols[i];
|
|
||||||
if (!strcasecmp(rSymbol.GetName().c_str(), name))
|
|
||||||
{
|
|
||||||
return (XSymbolIndex)i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid index
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This one can load both leftover map files on game discs (like Zelda), and mapfiles
|
|
||||||
// produced by SaveSymbolMap below.
|
|
||||||
bool LoadSymbolMap(const char *_szFilename)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
FILE *f = fopen(_szFilename, "r");
|
|
||||||
if (!f)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool started = false;
|
|
||||||
while (!feof(f))
|
|
||||||
{
|
|
||||||
char line[512],temp[256];
|
|
||||||
fgets(line, 511, f);
|
|
||||||
if (strlen(line) < 4)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sscanf(line,"%s",temp);
|
|
||||||
if (strcmp(temp,"UNUSED")==0) continue;
|
|
||||||
if (strcmp(temp,".text")==0) {started = true; continue;};
|
|
||||||
if (strcmp(temp,".init")==0) {started = true; continue;};
|
|
||||||
if (strcmp(temp,"Starting")==0) continue;
|
|
||||||
if (strcmp(temp,"extab")==0) continue;
|
|
||||||
if (strcmp(temp,".ctors")==0) break; //uh?
|
|
||||||
if (strcmp(temp,".dtors")==0) break;
|
|
||||||
if (strcmp(temp,".rodata")==0) continue;
|
|
||||||
if (strcmp(temp,".data")==0) continue;
|
|
||||||
if (strcmp(temp,".sbss")==0) continue;
|
|
||||||
if (strcmp(temp,".sdata")==0) continue;
|
|
||||||
if (strcmp(temp,".sdata2")==0) continue;
|
|
||||||
if (strcmp(temp,"address")==0) continue;
|
|
||||||
if (strcmp(temp,"-----------------------")==0) continue;
|
|
||||||
if (strcmp(temp,".sbss2")==0) break;
|
|
||||||
if (temp[1]==']') continue;
|
|
||||||
|
|
||||||
if (!started) continue;
|
|
||||||
|
|
||||||
u32 address, vaddress, size, unknown;
|
|
||||||
char name[512];
|
|
||||||
sscanf(line, "%08x %08x %08x %i %s", &address, &size, &vaddress, &unknown, name);
|
|
||||||
|
|
||||||
const char *namepos = strstr(line, name);
|
|
||||||
if (namepos != 0) //would be odd if not :P
|
|
||||||
strcpy(name, namepos);
|
|
||||||
name[strlen(name) - 1] = 0;
|
|
||||||
|
|
||||||
// we want the function names only .... TODO: or do we really? aren't we wasting information here?
|
|
||||||
for (size_t i = 0; i < strlen(name); i++)
|
|
||||||
{
|
|
||||||
if (name[i] == ' ') name[i] = 0x00;
|
|
||||||
if (name[i] == '(') name[i] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is a valid entry.
|
|
||||||
if (strcmp(name, ".text") != 0 || strcmp(name, ".init") != 0 || strlen(name) > 0)
|
|
||||||
{
|
|
||||||
AddSymbol(Symbol(vaddress | 0x80000000, size, ST_FUNCTION, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveSymbolMap(const char *_rFilename)
|
|
||||||
{
|
|
||||||
FILE *f = fopen(_rFilename,"w");
|
|
||||||
if (!f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(f,".text\n");
|
|
||||||
XVectorSymbol::const_iterator itr = g_Symbols.begin();
|
|
||||||
while (itr != g_Symbols.end())
|
|
||||||
{
|
|
||||||
const Symbol& rSymbol = *itr;
|
|
||||||
fprintf(f,"%08x %08x %08x %i %s\n",rSymbol.vaddress,rSymbol.size,rSymbol.vaddress,0,rSymbol.GetName().c_str());
|
|
||||||
itr++;
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushMapToFunctionDB(FunctionDB *func_db)
|
|
||||||
{
|
|
||||||
XVectorSymbol::const_iterator itr = g_Symbols.begin();
|
|
||||||
while (itr != g_Symbols.end())
|
|
||||||
{
|
|
||||||
const Symbol& rSymbol = *itr;
|
|
||||||
|
|
||||||
if (rSymbol.type == ST_FUNCTION && rSymbol.size>=12)
|
|
||||||
{
|
|
||||||
func_db->AddKnownFunction(rSymbol.vaddress, rSymbol.size / 4, rSymbol.GetName().c_str());
|
|
||||||
// if (!beginning || !strlen(beginning) || !(memcmp(beginning,rSymbol.name,strlen(beginning))))
|
|
||||||
// PPCAnalyst::AddToSignatureDB(rSymbol.vaddress, rSymbol.size, rSymbol.GetName().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
itr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetFromAnalyzer()
|
|
||||||
{
|
|
||||||
struct local {static void AddSymb(SFunction *f)
|
|
||||||
{
|
|
||||||
Debugger::AddSymbol(Symbol(f->address, f->size * 4, ST_FUNCTION, f->name.c_str()));
|
|
||||||
}};
|
|
||||||
g_funcDB.GetAllFuncs(local::AddSymb);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *GetDescription(u32 _Address)
|
|
||||||
{
|
|
||||||
Debugger::XSymbolIndex Index = Debugger::FindSymbol(_Address);
|
|
||||||
if (Index > 0)
|
|
||||||
return GetSymbol(Index).GetName().c_str();
|
|
||||||
else
|
|
||||||
return "(unk.)";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool GetCallstack(std::vector<CallstackEntry> &output)
|
bool GetCallstack(std::vector<CallstackEntry> &output)
|
||||||
{
|
{
|
||||||
if (Core::GetState() == Core::CORE_UNINITIALIZED)
|
if (Core::GetState() == Core::CORE_UNINITIALIZED)
|
||||||
@ -256,10 +45,10 @@ bool GetCallstack(std::vector<CallstackEntry> &output)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int count = 1;
|
int count = 1;
|
||||||
if (GetDescription(PowerPC::ppcState.pc) != GetDescription(LR))
|
if (g_symbolDB.GetDescription(PowerPC::ppcState.pc) != g_symbolDB.GetDescription(LR))
|
||||||
{
|
{
|
||||||
CallstackEntry entry;
|
CallstackEntry entry;
|
||||||
entry.Name = StringFromFormat(" * %s [ LR = %08x ]\n", Debugger::GetDescription(LR), LR);
|
entry.Name = StringFromFormat(" * %s [ LR = %08x ]\n", g_symbolDB.GetDescription(LR), LR);
|
||||||
entry.vAddress = 0x0;
|
entry.vAddress = 0x0;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -271,7 +60,7 @@ bool GetCallstack(std::vector<CallstackEntry> &output)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
u32 func = Memory::ReadUnchecked_U32(addr + 4);
|
u32 func = Memory::ReadUnchecked_U32(addr + 4);
|
||||||
const char *str = Debugger::GetDescription(func);
|
const char *str = g_symbolDB.GetDescription(func);
|
||||||
if (!str || strlen(str) == 0 || !strcmp(str, "Invalid"))
|
if (!str || strlen(str) == 0 || !strcmp(str, "Invalid"))
|
||||||
str = "(unknown)";
|
str = "(unknown)";
|
||||||
|
|
||||||
@ -289,7 +78,8 @@ bool GetCallstack(std::vector<CallstackEntry> &output)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintCallstack() {
|
void PrintCallstack()
|
||||||
|
{
|
||||||
u32 addr = Memory::ReadUnchecked_U32(PowerPC::ppcState.gpr[1]); // SP
|
u32 addr = Memory::ReadUnchecked_U32(PowerPC::ppcState.gpr[1]); // SP
|
||||||
|
|
||||||
printf("\n == STACK TRACE - SP = %08x ==\n", PowerPC::ppcState.gpr[1]);
|
printf("\n == STACK TRACE - SP = %08x ==\n", PowerPC::ppcState.gpr[1]);
|
||||||
@ -298,9 +88,9 @@ void PrintCallstack() {
|
|||||||
printf(" LR = 0 - this is bad\n");
|
printf(" LR = 0 - this is bad\n");
|
||||||
}
|
}
|
||||||
int count = 1;
|
int count = 1;
|
||||||
if (GetDescription(PowerPC::ppcState.pc) != GetDescription(LR))
|
if (g_symbolDB.GetDescription(PowerPC::ppcState.pc) != g_symbolDB.GetDescription(LR))
|
||||||
{
|
{
|
||||||
printf(" * %s [ LR = %08x ]\n", Debugger::GetDescription(LR), LR);
|
printf(" * %s [ LR = %08x ]\n", g_symbolDB.GetDescription(LR), LR);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +98,7 @@ void PrintCallstack() {
|
|||||||
while ((addr != 0xFFFFFFFF) && (addr != 0) && (count++ < 20) && (PowerPC::ppcState.gpr[1] != 0))
|
while ((addr != 0xFFFFFFFF) && (addr != 0) && (count++ < 20) && (PowerPC::ppcState.gpr[1] != 0))
|
||||||
{
|
{
|
||||||
u32 func = Memory::ReadUnchecked_U32(addr + 4);
|
u32 func = Memory::ReadUnchecked_U32(addr + 4);
|
||||||
const char *str = Debugger::GetDescription(func);
|
const char *str = g_symbolDB.GetDescription(func);
|
||||||
if (!str || strlen(str) == 0 || !strcmp(str, "Invalid"))
|
if (!str || strlen(str) == 0 || !strcmp(str, "Invalid"))
|
||||||
str = "(unknown)";
|
str = "(unknown)";
|
||||||
printf( " * %s [ addr = %08x ]\n", str, func);
|
printf( " * %s [ addr = %08x ]\n", str, func);
|
||||||
|
@ -23,62 +23,9 @@
|
|||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
class FunctionDB;
|
|
||||||
|
|
||||||
namespace Debugger
|
namespace Debugger
|
||||||
{
|
{
|
||||||
|
|
||||||
enum ESymbolType
|
|
||||||
{
|
|
||||||
ST_FUNCTION = 1,
|
|
||||||
ST_DATA = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
class Symbol
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 vaddress;
|
|
||||||
u32 size;
|
|
||||||
u32 runCount;
|
|
||||||
|
|
||||||
ESymbolType type;
|
|
||||||
|
|
||||||
Symbol(u32 _Address, u32 _Size, ESymbolType _Type, const char *_rName);
|
|
||||||
~Symbol();
|
|
||||||
|
|
||||||
const std::string &GetName() const { return m_strName; }
|
|
||||||
void SetName(const char *_rName) { m_strName = _rName; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_strName;
|
|
||||||
std::vector <u32> m_vecBackwardLinks;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int XSymbolIndex;
|
|
||||||
typedef std::vector<Symbol> XVectorSymbol;
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
XSymbolIndex AddSymbol(const Symbol& _rSymbolMapEntry);
|
|
||||||
|
|
||||||
const Symbol& GetSymbol(XSymbolIndex _Index);
|
|
||||||
Symbol& AccessSymbol(XSymbolIndex _Index);
|
|
||||||
|
|
||||||
const XVectorSymbol& AccessSymbols();
|
|
||||||
|
|
||||||
XSymbolIndex FindSymbol(u32 _Address);
|
|
||||||
XSymbolIndex FindSymbol(const char *name);
|
|
||||||
|
|
||||||
bool LoadSymbolMap(const char *_rFilename);
|
|
||||||
void SaveSymbolMap(const char *_rFilename);
|
|
||||||
|
|
||||||
const char *GetDescription(u32 _Address);
|
|
||||||
|
|
||||||
bool RenameSymbol(XSymbolIndex _Index, const char *_Name);
|
|
||||||
|
|
||||||
void GetFromAnalyzer();
|
|
||||||
void PushMapToFunctionDB(FunctionDB *func_db);
|
|
||||||
|
|
||||||
struct CallstackEntry
|
struct CallstackEntry
|
||||||
{
|
{
|
||||||
std::string Name;
|
std::string Name;
|
||||||
@ -88,17 +35,6 @@ struct CallstackEntry
|
|||||||
bool GetCallstack(std::vector<CallstackEntry> &output);
|
bool GetCallstack(std::vector<CallstackEntry> &output);
|
||||||
void PrintCallstack();
|
void PrintCallstack();
|
||||||
|
|
||||||
// TODO: move outta here
|
|
||||||
#ifdef _WIN32
|
|
||||||
}
|
|
||||||
#include <windows.h>
|
|
||||||
#include <windowsx.h>
|
|
||||||
namespace Debugger
|
|
||||||
{
|
|
||||||
void FillSymbolListBox(HWND listbox, ESymbolType symmask);
|
|
||||||
void FillListBoxBLinks(HWND listbox, XSymbolIndex Index);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // end of namespace Debugger
|
} // end of namespace Debugger
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "../Core.h"
|
#include "../Core.h"
|
||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
#include "../PowerPC/PowerPC.h"
|
#include "../PowerPC/PowerPC.h"
|
||||||
|
#include "../PowerPC/SymbolDB.h"
|
||||||
|
|
||||||
// Not thread safe.
|
// Not thread safe.
|
||||||
const char *PPCDebugInterface::disasm(unsigned int address)
|
const char *PPCDebugInterface::disasm(unsigned int address)
|
||||||
@ -82,15 +83,17 @@ int PPCDebugInterface::getColor(unsigned int address)
|
|||||||
{
|
{
|
||||||
if (!Memory::IsRAMAddress(address))
|
if (!Memory::IsRAMAddress(address))
|
||||||
return 0xeeeeee;
|
return 0xeeeeee;
|
||||||
int colors[6] = {0xe0FFFF,0xFFe0e0,0xe8e8FF,0xFFe0FF,0xe0FFe0,0xFFFFe0};
|
int colors[6] = {0xe0FFFF, 0xFFe0e0, 0xe8e8FF, 0xFFe0FF, 0xe0FFe0, 0xFFFFe0};
|
||||||
int n = Debugger::FindSymbol(address);
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(address);
|
||||||
if (n == -1) return 0xFFFFFF;
|
if (!symbol) return 0xFFFFFF;
|
||||||
return colors[n%6];
|
if (symbol->type != Symbol::SYMBOL_FUNCTION)
|
||||||
|
return 0xEEEEFF;
|
||||||
|
return colors[symbol->index % 6];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PPCDebugInterface::getDescription(unsigned int address)
|
std::string PPCDebugInterface::getDescription(unsigned int address)
|
||||||
{
|
{
|
||||||
return Debugger::GetDescription(address);
|
return g_symbolDB.GetDescription(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int PPCDebugInterface::getPC()
|
unsigned int PPCDebugInterface::getPC()
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "HLE.h"
|
#include "HLE.h"
|
||||||
|
|
||||||
#include "../PowerPC/PowerPC.h"
|
#include "../PowerPC/PowerPC.h"
|
||||||
|
#include "../PowerPC/SymbolDB.h"
|
||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
#include "../Debugger/Debugger_SymbolMap.h"
|
#include "../Debugger/Debugger_SymbolMap.h"
|
||||||
#include "../Debugger/Debugger_BreakPoints.h"
|
#include "../Debugger/Debugger_BreakPoints.h"
|
||||||
@ -99,28 +100,23 @@ void PatchFunctions()
|
|||||||
{
|
{
|
||||||
for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++)
|
for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++)
|
||||||
{
|
{
|
||||||
int SymbolIndex = Debugger::FindSymbol(OSPatches[i].m_szPatchName);
|
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
|
||||||
if (SymbolIndex > 0)
|
if (symbol > 0)
|
||||||
{
|
{
|
||||||
const Debugger::Symbol& symbol = Debugger::GetSymbol(SymbolIndex);
|
|
||||||
u32 HLEPatchValue = (1 & 0x3f) << 26;
|
u32 HLEPatchValue = (1 & 0x3f) << 26;
|
||||||
for (size_t addr = symbol.vaddress; addr < symbol.vaddress + symbol.size; addr += 4) {
|
for (size_t addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
|
||||||
Memory::Write_U32(HLEPatchValue | i, addr);
|
Memory::Write_U32(HLEPatchValue | i, addr);
|
||||||
}
|
LOG(HLE,"Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address);
|
||||||
//PanicAlert("patched %s", OSPatches[i].m_szPatchName);
|
|
||||||
LOG(HLE,"Patching %s %08x", OSPatches[i].m_szPatchName, symbol.vaddress);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 1; i < sizeof(OSBreakPoints) / sizeof(SPatch); i++)
|
for (size_t i = 1; i < sizeof(OSBreakPoints) / sizeof(SPatch); i++)
|
||||||
{
|
{
|
||||||
int SymbolIndex = Debugger::FindSymbol(OSBreakPoints[i].m_szPatchName);
|
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
|
||||||
if (SymbolIndex != -1)
|
if (symbol > 0)
|
||||||
{
|
{
|
||||||
const Debugger::Symbol& symbol = Debugger::GetSymbol(SymbolIndex);
|
CBreakPoints::AddBreakPoint(symbol->address, false);
|
||||||
CBreakPoints::AddBreakPoint(symbol.vaddress, false);
|
LOG(HLE,"Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol->address);
|
||||||
|
|
||||||
LOG(HLE,"Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol.vaddress);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF
|
|||||||
status = MC_STATUS_BUSY | MC_STATUS_UNLOCKED | MC_STATUS_READY;
|
status = MC_STATUS_BUSY | MC_STATUS_UNLOCKED | MC_STATUS_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIMemoryCard::Flush()
|
void CEXIMemoryCard::Flush(bool exiting)
|
||||||
{
|
{
|
||||||
FILE* pFile = NULL;
|
FILE* pFile = NULL;
|
||||||
pFile = fopen(m_strFilename.c_str(), "wb");
|
pFile = fopen(m_strFilename.c_str(), "wb");
|
||||||
@ -97,13 +97,14 @@ void CEXIMemoryCard::Flush()
|
|||||||
}
|
}
|
||||||
fwrite(memory_card_content, memory_card_size, 1, pFile);
|
fwrite(memory_card_content, memory_card_size, 1, pFile);
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
Core::DisplayMessage(StringFromFormat("Wrote memory card contents to %s", GetFileName().c_str()), 4000);
|
if (!exiting)
|
||||||
|
Core::DisplayMessage(StringFromFormat("Wrote memory card contents to %s", GetFileName().c_str()), 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CEXIMemoryCard::~CEXIMemoryCard()
|
CEXIMemoryCard::~CEXIMemoryCard()
|
||||||
{
|
{
|
||||||
Flush();
|
Flush(true);
|
||||||
delete [] memory_card_content;
|
delete [] memory_card_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ private:
|
|||||||
static void FlushCallback(u64 userdata, int cyclesLate);
|
static void FlushCallback(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
// Flushes the memory card contents to disk.
|
// Flushes the memory card contents to disk.
|
||||||
void Flush();
|
void Flush(bool exiting = false);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -167,7 +167,7 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...)
|
|||||||
|
|
||||||
char* Msg2 = (char*)alloca(strlen(_fmt)+512);
|
char* Msg2 = (char*)alloca(strlen(_fmt)+512);
|
||||||
|
|
||||||
Debugger::XSymbolIndex Index = 0; //Debugger::FindSymbol(PC);
|
int Index = 0; //Debugger::FindSymbol(PC);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const char *eol = "\x0D\x0A";
|
const char *eol = "\x0D\x0A";
|
||||||
#else
|
#else
|
||||||
@ -175,12 +175,12 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
if (Index > 0)
|
if (Index > 0)
|
||||||
{
|
{
|
||||||
const Debugger::Symbol& symbol = Debugger::GetSymbol(Index);
|
// const Debugger::Symbol& symbol = Debugger::GetSymbol(Index);
|
||||||
sprintf(Msg2, "%i: %x %s (%s, %08x ) : %s%s",
|
sprintf(Msg2, "%i: %x %s (%s, %08x ) : %s%s",
|
||||||
++count,
|
++count,
|
||||||
PowerPC::ppcState.DebugCount,
|
PowerPC::ppcState.DebugCount,
|
||||||
m_Log[_type]->m_szShortName,
|
m_Log[_type]->m_szShortName,
|
||||||
symbol.GetName().c_str(),
|
"", //symbol.GetName().c_str(),
|
||||||
PC,
|
PC,
|
||||||
Msg, eol);
|
Msg, eol);
|
||||||
}
|
}
|
||||||
|
@ -1,170 +0,0 @@
|
|||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, version 2.0.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License 2.0 for more details.
|
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||||
// If not, see http://www.gnu.org/licenses/
|
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
|
||||||
// http://code.google.com/p/dolphin-emu/
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "FunctionDB.h"
|
|
||||||
#include "SignatureDB.h"
|
|
||||||
#include "PPCAnalyst.h"
|
|
||||||
|
|
||||||
FunctionDB g_funcDB;
|
|
||||||
|
|
||||||
void FunctionDB::List()
|
|
||||||
{
|
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
|
||||||
{
|
|
||||||
LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls",iter->second.name.c_str(),iter->second.address,iter->second.size,iter->second.hash,iter->second.numCalls);
|
|
||||||
}
|
|
||||||
LOG(HLE,"%i functions known in this program above.",functions.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::Clear()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds the function to the list, unless it's already there
|
|
||||||
SFunction *FunctionDB::AddFunction(u32 startAddr)
|
|
||||||
{
|
|
||||||
if (startAddr < 0x80000010)
|
|
||||||
return 0;
|
|
||||||
XFuncMap::iterator iter = functions.find(startAddr);
|
|
||||||
if (iter != functions.end())
|
|
||||||
{
|
|
||||||
// it's already in the list
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SFunction tempFunc; //the current one we're working on
|
|
||||||
u32 targetEnd = PPCAnalyst::AnalyzeFunction(startAddr, tempFunc);
|
|
||||||
if (targetEnd == 0)
|
|
||||||
return 0; //found a dud :(
|
|
||||||
//LOG(HLE,"SFunction found at %08x",startAddr);
|
|
||||||
functions[startAddr] = tempFunc;
|
|
||||||
checksumToFunction[tempFunc.hash] = &(functions[startAddr]);
|
|
||||||
return &functions[startAddr];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::AddKnownFunction(u32 startAddr, u32 size, const char *name)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator iter = functions.find(startAddr);
|
|
||||||
if (iter != functions.end())
|
|
||||||
{
|
|
||||||
SFunction *tempfunc = &iter->second;
|
|
||||||
tempfunc->name = name;
|
|
||||||
tempfunc->hash = SignatureDB::ComputeCodeChecksum(startAddr, startAddr + size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SFunction tf;
|
|
||||||
tf.name = name;
|
|
||||||
PPCAnalyst::AnalyzeFunction(startAddr, tf);
|
|
||||||
functions[startAddr] = tf;
|
|
||||||
checksumToFunction[tf.hash] = &(functions[startAddr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::FillInCallers()
|
|
||||||
{
|
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter!=functions.end(); iter++)
|
|
||||||
{
|
|
||||||
SFunction &f = iter->second;
|
|
||||||
for (size_t i=0; i<f.calls.size(); i++)
|
|
||||||
{
|
|
||||||
SCall NewCall(iter->first, f.calls[i].callAddress);
|
|
||||||
u32 FunctionAddress = f.calls[i].function;
|
|
||||||
XFuncMap::iterator FuncIterator = functions.find(FunctionAddress);
|
|
||||||
if (FuncIterator != functions.end())
|
|
||||||
{
|
|
||||||
SFunction& rCalledFunction = FuncIterator->second;
|
|
||||||
rCalledFunction.callers.push_back(NewCall);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(HLE,"FillInCallers tries to fill data in an unknown fuction 0x%08x.", FunctionAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::PrintCalls(u32 funcAddr)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator iter = functions.find(funcAddr);
|
|
||||||
if (iter != functions.end())
|
|
||||||
{
|
|
||||||
SFunction &f = iter->second;
|
|
||||||
LOG(HLE, "The function %s at %08x calls:", f.name.c_str(), f.address);
|
|
||||||
for (std::vector<SCall>::iterator fiter = f.calls.begin(); fiter!=f.calls.end(); fiter++)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator n = functions.find(fiter->function);
|
|
||||||
if (n != functions.end())
|
|
||||||
{
|
|
||||||
LOG(CONSOLE,"* %08x : %s", fiter->callAddress, n->second.name.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(CONSOLE,"SFunction does not exist");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::PrintCallers(u32 funcAddr)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator iter = functions.find(funcAddr);
|
|
||||||
if (iter != functions.end())
|
|
||||||
{
|
|
||||||
SFunction &f = iter->second;
|
|
||||||
LOG(CONSOLE,"The function %s at %08x is called by:",f.name.c_str(),f.address);
|
|
||||||
for (std::vector<SCall>::iterator fiter = f.callers.begin(); fiter != f.callers.end(); fiter++)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator n = functions.find(fiter->function);
|
|
||||||
if (n != functions.end())
|
|
||||||
{
|
|
||||||
LOG(CONSOLE,"* %08x : %s", fiter->callAddress, n->second.name.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::GetAllFuncs(functionGetterCallback callback)
|
|
||||||
{
|
|
||||||
XFuncMap::iterator iter = functions.begin();
|
|
||||||
while (iter != functions.end())
|
|
||||||
{
|
|
||||||
callback(&(iter->second));
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDB::LogFunctionCall(u32 addr)
|
|
||||||
{
|
|
||||||
//u32 from = PC;
|
|
||||||
XFuncMap::iterator iter = functions.find(addr);
|
|
||||||
if (iter != functions.end())
|
|
||||||
{
|
|
||||||
SFunction &f = iter->second;
|
|
||||||
f.numCalls++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
|||||||
#include "Interpreter/Interpreter.h"
|
#include "Interpreter/Interpreter.h"
|
||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
#include "PPCTables.h"
|
#include "PPCTables.h"
|
||||||
#include "FunctionDB.h"
|
#include "SymbolDB.h"
|
||||||
#include "SignatureDB.h"
|
#include "SignatureDB.h"
|
||||||
#include "PPCAnalyst.h"
|
#include "PPCAnalyst.h"
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ using namespace std;
|
|||||||
// VERY ugly. TODO: remove.
|
// VERY ugly. TODO: remove.
|
||||||
PPCAnalyst::CodeOp codebuffer[20000];
|
PPCAnalyst::CodeOp codebuffer[20000];
|
||||||
|
|
||||||
void AnalyzeFunction2(SFunction &func);
|
void AnalyzeFunction2(Symbol &func);
|
||||||
u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc);
|
u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc);
|
||||||
|
|
||||||
// void FixUpInternalBranches(CodeOp *code, int begin, int end);
|
// void FixUpInternalBranches(CodeOp *code, int begin, int end);
|
||||||
@ -73,7 +73,7 @@ u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc)
|
|||||||
//If any one goes farther than the blr, assume that there is more than
|
//If any one goes farther than the blr, assume that there is more than
|
||||||
//one blr, and keep scanning.
|
//one blr, and keep scanning.
|
||||||
|
|
||||||
bool AnalyzeFunction(u32 startAddr, SFunction &func)
|
bool AnalyzeFunction(u32 startAddr, Symbol &func)
|
||||||
{
|
{
|
||||||
if (!func.name.size())
|
if (!func.name.size())
|
||||||
func.name = StringFromFormat("zzz_%08x ??", startAddr);
|
func.name = StringFromFormat("zzz_%08x ??", startAddr);
|
||||||
@ -110,7 +110,9 @@ bool AnalyzeFunction(u32 startAddr, SFunction &func)
|
|||||||
//a final blr!
|
//a final blr!
|
||||||
//We're done! Looks like we have a neat valid function. Perfect.
|
//We're done! Looks like we have a neat valid function. Perfect.
|
||||||
//Let's calc the checksum and get outta here
|
//Let's calc the checksum and get outta here
|
||||||
|
func.size *= 4; // into bytes
|
||||||
func.address = startAddr;
|
func.address = startAddr;
|
||||||
|
func.analyzed = 1;
|
||||||
func.hash = SignatureDB::ComputeCodeChecksum(startAddr, addr);
|
func.hash = SignatureDB::ComputeCodeChecksum(startAddr, addr);
|
||||||
if (numInternalBranches == 0)
|
if (numInternalBranches == 0)
|
||||||
func.flags |= FFLAG_STRAIGHT;
|
func.flags |= FFLAG_STRAIGHT;
|
||||||
@ -165,7 +167,7 @@ bool AnalyzeFunction(u32 startAddr, SFunction &func)
|
|||||||
|
|
||||||
// Second pass analysis, done after the first pass is done for all functions
|
// Second pass analysis, done after the first pass is done for all functions
|
||||||
// so we have more information to work with
|
// so we have more information to work with
|
||||||
void AnalyzeFunction2(SFunction &func)
|
void AnalyzeFunction2(Symbol &func)
|
||||||
{
|
{
|
||||||
// u32 addr = func.address;
|
// u32 addr = func.address;
|
||||||
u32 flags = func.flags;
|
u32 flags = func.flags;
|
||||||
@ -193,7 +195,7 @@ void AnalyzeFunction2(SFunction &func)
|
|||||||
for (size_t i = 0; i < func.calls.size(); i++)
|
for (size_t i = 0; i < func.calls.size(); i++)
|
||||||
{
|
{
|
||||||
SCall c = func.calls[i];
|
SCall c = func.calls[i];
|
||||||
SFunction *called_func = g_funcDB.GetFunction(c.function);
|
Symbol *called_func = g_symbolDB.GetSymbolFromAddr(c.function);
|
||||||
if (called_func && (called_func->flags & FFLAG_LEAF) == 0)
|
if (called_func && (called_func->flags & FFLAG_LEAF) == 0)
|
||||||
{
|
{
|
||||||
nonleafcall = true;
|
nonleafcall = true;
|
||||||
@ -272,7 +274,7 @@ CodeOp *Flatten(u32 address, u32 &realsize, BlockStats &st, BlockRegStats &gpa,
|
|||||||
};
|
};
|
||||||
Todo todo = Nothing;
|
Todo todo = Nothing;
|
||||||
|
|
||||||
SFunction *f = g_funcDB.GetFunction(address);
|
Symbol *f = g_symbolDB.GetSymbolFromAddr(address);
|
||||||
int maxsize = 20000;
|
int maxsize = 20000;
|
||||||
//for now, all will return JustCopy :P
|
//for now, all will return JustCopy :P
|
||||||
if (f)
|
if (f)
|
||||||
@ -548,8 +550,7 @@ CodeOp *Flatten(u32 address, u32 &realsize, BlockStats &st, BlockRegStats &gpa,
|
|||||||
// called by another function. Therefore, let's scan the
|
// called by another function. Therefore, let's scan the
|
||||||
// entire space for bl operations and find what functions
|
// entire space for bl operations and find what functions
|
||||||
// get called.
|
// get called.
|
||||||
|
void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, SymbolDB *func_db)
|
||||||
void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, FunctionDB *func_db)
|
|
||||||
{
|
{
|
||||||
for (u32 addr = startAddr; addr < endAddr; addr+=4)
|
for (u32 addr = startAddr; addr < endAddr; addr+=4)
|
||||||
{
|
{
|
||||||
@ -580,12 +581,12 @@ void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, FunctionDB *func_db)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindFunctionsAfterBLR(FunctionDB *func_db)
|
void FindFunctionsAfterBLR(SymbolDB *func_db)
|
||||||
{
|
{
|
||||||
vector<u32> funcAddrs;
|
vector<u32> funcAddrs;
|
||||||
|
|
||||||
for (FunctionDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); iter++)
|
for (SymbolDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); iter++)
|
||||||
funcAddrs.push_back(iter->second.address + iter->second.size*4);
|
funcAddrs.push_back(iter->second.address + iter->second.size);
|
||||||
|
|
||||||
for (vector<u32>::iterator iter = funcAddrs.begin(); iter != funcAddrs.end(); iter++)
|
for (vector<u32>::iterator iter = funcAddrs.begin(); iter != funcAddrs.end(); iter++)
|
||||||
{
|
{
|
||||||
@ -595,11 +596,11 @@ void FindFunctionsAfterBLR(FunctionDB *func_db)
|
|||||||
if (PPCTables::IsValidInstruction(Memory::Read_Instruction(location)))
|
if (PPCTables::IsValidInstruction(Memory::Read_Instruction(location)))
|
||||||
{
|
{
|
||||||
//check if this function is already mapped
|
//check if this function is already mapped
|
||||||
SFunction *f = func_db->AddFunction(location);
|
Symbol *f = func_db->AddFunction(location);
|
||||||
if (!f)
|
if (!f)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
location += f->size * 4;
|
location += f->size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -607,7 +608,7 @@ void FindFunctionsAfterBLR(FunctionDB *func_db)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCAnalyst::FindFunctions(u32 startAddr, u32 endAddr, FunctionDB *func_db)
|
void PPCAnalyst::FindFunctions(u32 startAddr, u32 endAddr, SymbolDB *func_db)
|
||||||
{
|
{
|
||||||
//Step 1: Find all functions
|
//Step 1: Find all functions
|
||||||
FindFunctionsFromBranches(startAddr, endAddr, func_db);
|
FindFunctionsFromBranches(startAddr, endAddr, func_db);
|
||||||
@ -618,7 +619,7 @@ void PPCAnalyst::FindFunctions(u32 startAddr, u32 endAddr, FunctionDB *func_db)
|
|||||||
|
|
||||||
int numLeafs = 0, numNice = 0, numUnNice = 0, numTimer=0, numRFI=0, numStraightLeaf=0;
|
int numLeafs = 0, numNice = 0, numUnNice = 0, numTimer=0, numRFI=0, numStraightLeaf=0;
|
||||||
int leafSize = 0, niceSize = 0, unniceSize = 0;
|
int leafSize = 0, niceSize = 0, unniceSize = 0;
|
||||||
for (FunctionDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); iter++)
|
for (SymbolDB::XFuncMap::iterator iter = func_db->GetIterator(); iter != func_db->End(); iter++)
|
||||||
{
|
{
|
||||||
if (iter->second.address == 4)
|
if (iter->second.address == 4)
|
||||||
{
|
{
|
||||||
@ -626,7 +627,7 @@ void PPCAnalyst::FindFunctions(u32 startAddr, u32 endAddr, FunctionDB *func_db)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AnalyzeFunction2(iter->second);
|
AnalyzeFunction2(iter->second);
|
||||||
SFunction &f = iter->second;
|
Symbol &f = iter->second;
|
||||||
if (f.flags & FFLAG_LEAF)
|
if (f.flags & FFLAG_LEAF)
|
||||||
{
|
{
|
||||||
numLeafs++;
|
numLeafs++;
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Gekko.h"
|
#include "Gekko.h"
|
||||||
|
|
||||||
class FunctionDB;
|
class SymbolDB;
|
||||||
struct SFunction;
|
struct Symbol;
|
||||||
|
|
||||||
namespace PPCAnalyst
|
namespace PPCAnalyst
|
||||||
{
|
{
|
||||||
@ -82,8 +82,8 @@ namespace PPCAnalyst
|
|||||||
|
|
||||||
void LogFunctionCall(u32 addr);
|
void LogFunctionCall(u32 addr);
|
||||||
|
|
||||||
void FindFunctions(u32 startAddr, u32 endAddr, FunctionDB *func_db);
|
void FindFunctions(u32 startAddr, u32 endAddr, SymbolDB *func_db);
|
||||||
bool AnalyzeFunction(u32 startAddr, SFunction &func);
|
bool AnalyzeFunction(u32 startAddr, Symbol &func);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "../HW/Memmap.h"
|
#include "../HW/Memmap.h"
|
||||||
|
|
||||||
#include "SignatureDB.h"
|
#include "SignatureDB.h"
|
||||||
#include "FunctionDB.h"
|
#include "SymbolDB.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -109,31 +109,33 @@ void SignatureDB::Clear()
|
|||||||
database.clear();
|
database.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignatureDB::Apply(FunctionDB *func_db)
|
void SignatureDB::Apply(SymbolDB *symbol_db)
|
||||||
{
|
{
|
||||||
for (FuncDB::const_iterator iter = database.begin(); iter != database.end(); iter++)
|
for (FuncDB::const_iterator iter = database.begin(); iter != database.end(); iter++)
|
||||||
{
|
{
|
||||||
u32 checkSum = iter->first;
|
u32 hash = iter->first;
|
||||||
SFunction *function = func_db->GetFunction(checkSum);
|
Symbol *function = symbol_db->GetSymbolFromHash(hash);
|
||||||
if (function)
|
if (function)
|
||||||
{
|
{
|
||||||
// Found the function. Let's rename it according to the symbol file.
|
// Found the function. Let's rename it according to the symbol file.
|
||||||
if (iter->second.size == (unsigned int)function->size * 4)
|
if (iter->second.size == (unsigned int)function->size)
|
||||||
{
|
{
|
||||||
function->name = iter->second.name;
|
function->name = iter->second.name;
|
||||||
LOG(HLE,"Found %s at %08x (size: %08x)!", iter->second.name.c_str(), function->address, function->size);
|
LOG(HLE, "Found %s at %08x (size: %08x)!", iter->second.name.c_str(), function->address, function->size);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
function->name = iter->second.name;
|
function->name = iter->second.name;
|
||||||
LOG(HLE,"Wrong sizzze! Found %s at %08x (size: %08x instead of %08x)!", iter->second.name.c_str(), function->address, function->size, iter->second.size);
|
LOG(HLE, "Wrong sizzze! Found %s at %08x (size: %08x instead of %08x)!", iter->second.name.c_str(), function->address, function->size, iter->second.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
symbol_db->Index();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignatureDB::Initialize(FunctionDB *func_db)
|
void SignatureDB::Initialize(SymbolDB *symbol_db)
|
||||||
{
|
{
|
||||||
for (FunctionDB::XFuncMap::const_iterator iter = func_db->GetConstIterator(); iter != func_db->End(); iter++)
|
for (SymbolDB::XFuncMap::const_iterator iter = symbol_db->GetConstIterator(); iter != symbol_db->End(); iter++)
|
||||||
{
|
{
|
||||||
DBFunc temp_dbfunc;
|
DBFunc temp_dbfunc;
|
||||||
temp_dbfunc.name = iter->second.name;
|
temp_dbfunc.name = iter->second.name;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
// You're not meant to keep around SignatureDB objects persistently. Use 'em, throw them away.
|
// You're not meant to keep around SignatureDB objects persistently. Use 'em, throw them away.
|
||||||
|
|
||||||
class FunctionDB;
|
class SymbolDB;
|
||||||
|
|
||||||
class SignatureDB
|
class SignatureDB
|
||||||
{
|
{
|
||||||
@ -50,8 +50,8 @@ public:
|
|||||||
void Clear();
|
void Clear();
|
||||||
void List();
|
void List();
|
||||||
|
|
||||||
void Initialize(FunctionDB *func_db);
|
void Initialize(SymbolDB *func_db);
|
||||||
void Apply(FunctionDB *func_db);
|
void Apply(SymbolDB *func_db);
|
||||||
|
|
||||||
static u32 ComputeCodeChecksum(u32 offsetStart, u32 offsetEnd);
|
static u32 ComputeCodeChecksum(u32 offsetStart, u32 offsetEnd);
|
||||||
};
|
};
|
||||||
|
293
Source/Core/Core/Src/PowerPC/SymbolDB.cpp
Normal file
293
Source/Core/Core/Src/PowerPC/SymbolDB.cpp
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SymbolDB.h"
|
||||||
|
#include "SignatureDB.h"
|
||||||
|
#include "PPCAnalyst.h"
|
||||||
|
|
||||||
|
SymbolDB g_symbolDB;
|
||||||
|
|
||||||
|
void SymbolDB::List()
|
||||||
|
{
|
||||||
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
|
{
|
||||||
|
LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
|
||||||
|
}
|
||||||
|
LOG(HLE,"%i functions known in this program above.", functions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::Clear()
|
||||||
|
{
|
||||||
|
functions.clear();
|
||||||
|
checksumToFunction.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::Index()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
|
{
|
||||||
|
iter->second.index = i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the function to the list, unless it's already there
|
||||||
|
Symbol *SymbolDB::AddFunction(u32 startAddr)
|
||||||
|
{
|
||||||
|
if (startAddr < 0x80000010)
|
||||||
|
return 0;
|
||||||
|
XFuncMap::iterator iter = functions.find(startAddr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
{
|
||||||
|
// it's already in the list
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Symbol tempFunc; //the current one we're working on
|
||||||
|
u32 targetEnd = PPCAnalyst::AnalyzeFunction(startAddr, tempFunc);
|
||||||
|
if (targetEnd == 0)
|
||||||
|
return 0; //found a dud :(
|
||||||
|
//LOG(HLE,"Symbol found at %08x",startAddr);
|
||||||
|
functions[startAddr] = tempFunc;
|
||||||
|
tempFunc.type = Symbol::SYMBOL_FUNCTION;
|
||||||
|
checksumToFunction[tempFunc.hash] = &(functions[startAddr]);
|
||||||
|
return &functions[startAddr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::AddKnownSymbol(u32 startAddr, u32 size, const char *name, int type)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator iter = functions.find(startAddr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
{
|
||||||
|
// already got it, let's just update name and checksum to be sure.
|
||||||
|
Symbol *tempfunc = &iter->second;
|
||||||
|
tempfunc->name = name;
|
||||||
|
tempfunc->hash = SignatureDB::ComputeCodeChecksum(startAddr, startAddr + size);
|
||||||
|
tempfunc->type = type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// new symbol. run analyze.
|
||||||
|
Symbol tf;
|
||||||
|
tf.name = name;
|
||||||
|
tf.type = type;
|
||||||
|
if (tf.type == Symbol::SYMBOL_FUNCTION) {
|
||||||
|
PPCAnalyst::AnalyzeFunction(startAddr, tf);
|
||||||
|
checksumToFunction[tf.hash] = &(functions[startAddr]);
|
||||||
|
}
|
||||||
|
functions[startAddr] = tf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol *SymbolDB::GetSymbolFromAddr(u32 addr)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator iter = functions.find(addr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
return &iter->second;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
|
{
|
||||||
|
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
|
||||||
|
return &iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol *SymbolDB::GetSymbolFromName(const char *name)
|
||||||
|
{
|
||||||
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
|
{
|
||||||
|
if (!strcmp(iter->second.name.c_str(), name))
|
||||||
|
return &iter->second;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SymbolDB::GetDescription(u32 addr)
|
||||||
|
{
|
||||||
|
Symbol *symbol = GetSymbolFromAddr(addr);
|
||||||
|
if (symbol)
|
||||||
|
return symbol->name.c_str();
|
||||||
|
else
|
||||||
|
return " --- ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::FillInCallers()
|
||||||
|
{
|
||||||
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
|
{
|
||||||
|
Symbol &f = iter->second;
|
||||||
|
for (size_t i = 0; i < f.calls.size(); i++)
|
||||||
|
{
|
||||||
|
SCall NewCall(iter->first, f.calls[i].callAddress);
|
||||||
|
u32 FunctionAddress = f.calls[i].function;
|
||||||
|
XFuncMap::iterator FuncIterator = functions.find(FunctionAddress);
|
||||||
|
if (FuncIterator != functions.end())
|
||||||
|
{
|
||||||
|
Symbol& rCalledFunction = FuncIterator->second;
|
||||||
|
rCalledFunction.callers.push_back(NewCall);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(HLE,"FillInCallers tries to fill data in an unknown function 0x%08x.", FunctionAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::PrintCalls(u32 funcAddr)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator iter = functions.find(funcAddr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
{
|
||||||
|
Symbol &f = iter->second;
|
||||||
|
LOG(HLE, "The function %s at %08x calls:", f.name.c_str(), f.address);
|
||||||
|
for (std::vector<SCall>::iterator fiter = f.calls.begin(); fiter!=f.calls.end(); fiter++)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator n = functions.find(fiter->function);
|
||||||
|
if (n != functions.end())
|
||||||
|
{
|
||||||
|
LOG(CONSOLE,"* %08x : %s", fiter->callAddress, n->second.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(CONSOLE, "Symbol does not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::PrintCallers(u32 funcAddr)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator iter = functions.find(funcAddr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
{
|
||||||
|
Symbol &f = iter->second;
|
||||||
|
LOG(CONSOLE,"The function %s at %08x is called by:",f.name.c_str(),f.address);
|
||||||
|
for (std::vector<SCall>::iterator fiter = f.callers.begin(); fiter != f.callers.end(); fiter++)
|
||||||
|
{
|
||||||
|
XFuncMap::iterator n = functions.find(fiter->function);
|
||||||
|
if (n != functions.end())
|
||||||
|
{
|
||||||
|
LOG(CONSOLE,"* %08x : %s", fiter->callAddress, n->second.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolDB::LogFunctionCall(u32 addr)
|
||||||
|
{
|
||||||
|
//u32 from = PC;
|
||||||
|
XFuncMap::iterator iter = functions.find(addr);
|
||||||
|
if (iter != functions.end())
|
||||||
|
{
|
||||||
|
Symbol &f = iter->second;
|
||||||
|
f.numCalls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This one can load both leftover map files on game discs (like Zelda), and mapfiles
|
||||||
|
// produced by SaveSymbolMap below.
|
||||||
|
bool SymbolDB::LoadMap(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "r");
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool started = false;
|
||||||
|
while (!feof(f))
|
||||||
|
{
|
||||||
|
char line[512],temp[256];
|
||||||
|
fgets(line, 511, f);
|
||||||
|
if (strlen(line) < 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sscanf(line,"%s",temp);
|
||||||
|
if (strcmp(temp,"UNUSED")==0) continue;
|
||||||
|
if (strcmp(temp,".text")==0) {started = true; continue;};
|
||||||
|
if (strcmp(temp,".init")==0) {started = true; continue;};
|
||||||
|
if (strcmp(temp,"Starting")==0) continue;
|
||||||
|
if (strcmp(temp,"extab")==0) continue;
|
||||||
|
if (strcmp(temp,".ctors")==0) break; //uh?
|
||||||
|
if (strcmp(temp,".dtors")==0) break;
|
||||||
|
if (strcmp(temp,".rodata")==0) continue;
|
||||||
|
if (strcmp(temp,".data")==0) continue;
|
||||||
|
if (strcmp(temp,".sbss")==0) continue;
|
||||||
|
if (strcmp(temp,".sdata")==0) continue;
|
||||||
|
if (strcmp(temp,".sdata2")==0) continue;
|
||||||
|
if (strcmp(temp,"address")==0) continue;
|
||||||
|
if (strcmp(temp,"-----------------------")==0) continue;
|
||||||
|
if (strcmp(temp,".sbss2")==0) break;
|
||||||
|
if (temp[1] == ']') continue;
|
||||||
|
|
||||||
|
if (!started) continue;
|
||||||
|
|
||||||
|
u32 address, vaddress, size, unknown;
|
||||||
|
char name[512];
|
||||||
|
sscanf(line, "%08x %08x %08x %i %s", &address, &size, &vaddress, &unknown, name);
|
||||||
|
|
||||||
|
const char *namepos = strstr(line, name);
|
||||||
|
if (namepos != 0) //would be odd if not :P
|
||||||
|
strcpy(name, namepos);
|
||||||
|
name[strlen(name) - 1] = 0;
|
||||||
|
|
||||||
|
// we want the function names only .... TODO: or do we really? aren't we wasting information here?
|
||||||
|
for (size_t i = 0; i < strlen(name); i++)
|
||||||
|
{
|
||||||
|
if (name[i] == ' ') name[i] = 0x00;
|
||||||
|
if (name[i] == '(') name[i] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a valid entry.
|
||||||
|
if (strcmp(name, ".text") != 0 || strcmp(name, ".init") != 0 || strlen(name) > 0)
|
||||||
|
{
|
||||||
|
AddKnownSymbol(vaddress | 0x80000000, size, name); // ST_FUNCTION
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
Index();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SymbolDB::SaveMap(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "w");
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fprintf(f,".text\n");
|
||||||
|
XFuncMap::const_iterator itr = functions.begin();
|
||||||
|
while (itr != functions.end())
|
||||||
|
{
|
||||||
|
const Symbol &rSymbol = itr->second;
|
||||||
|
fprintf(f,"%08x %08x %08x %i %s\n", rSymbol.address, rSymbol.size, rSymbol.address, 0, rSymbol.name.c_str());
|
||||||
|
itr++;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
@ -31,18 +31,24 @@ struct SCall
|
|||||||
u32 callAddress;
|
u32 callAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SFunction
|
struct Symbol
|
||||||
{
|
{
|
||||||
SFunction() :
|
enum {
|
||||||
|
SYMBOL_FUNCTION = 0,
|
||||||
|
SYMBOL_DATA = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Symbol() :
|
||||||
hash(0),
|
hash(0),
|
||||||
address(0),
|
address(0),
|
||||||
flags(0),
|
flags(0),
|
||||||
size(0),
|
size(0),
|
||||||
numCalls(0),
|
numCalls(0),
|
||||||
analyzed(0)
|
analyzed(0),
|
||||||
|
type(SYMBOL_FUNCTION)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~SFunction()
|
~Symbol()
|
||||||
{
|
{
|
||||||
callers.clear();
|
callers.clear();
|
||||||
calls.clear();
|
calls.clear();
|
||||||
@ -56,6 +62,8 @@ struct SFunction
|
|||||||
u32 flags;
|
u32 flags;
|
||||||
int size;
|
int size;
|
||||||
int numCalls;
|
int numCalls;
|
||||||
|
int type;
|
||||||
|
int index; // only used for coloring the disasm view
|
||||||
|
|
||||||
int analyzed;
|
int analyzed;
|
||||||
};
|
};
|
||||||
@ -72,42 +80,55 @@ enum
|
|||||||
|
|
||||||
|
|
||||||
// This has functionality overlapping Debugger_Symbolmap. Should merge that stuff in here later.
|
// This has functionality overlapping Debugger_Symbolmap. Should merge that stuff in here later.
|
||||||
class FunctionDB
|
class SymbolDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<u32, SFunction> XFuncMap;
|
typedef std::map<u32, Symbol> XFuncMap;
|
||||||
typedef std::map<u32, SFunction*> XFuncPtrMap;
|
typedef std::map<u32, Symbol*> XFuncPtrMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XFuncMap functions;
|
XFuncMap functions;
|
||||||
XFuncPtrMap checksumToFunction;
|
XFuncPtrMap checksumToFunction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef void (*functionGetterCallback)(Symbol *f);
|
||||||
typedef void (*functionGetterCallback)(SFunction *f);
|
|
||||||
|
|
||||||
FunctionDB() {}
|
SymbolDB() {}
|
||||||
|
|
||||||
SFunction *AddFunction(u32 startAddr);
|
Symbol *AddFunction(u32 startAddr);
|
||||||
void AddKnownFunction(u32 startAddr, u32 size, const char *name);
|
void AddKnownSymbol(u32 startAddr, u32 size, const char *name, int type = Symbol::SYMBOL_FUNCTION);
|
||||||
|
|
||||||
void GetAllFuncs(functionGetterCallback callback);
|
Symbol *GetSymbolFromAddr(u32 addr);
|
||||||
SFunction *GetFunction(u32 hash) {
|
Symbol *GetSymbolFromName(const char *name);
|
||||||
// TODO: sanity check
|
Symbol *GetSymbolFromHash(u32 hash) {
|
||||||
return checksumToFunction[hash];
|
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
|
||||||
|
if (iter != checksumToFunction.end())
|
||||||
|
return iter->second;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const XFuncMap &Symbols() const {return functions;}
|
||||||
|
XFuncMap &AccessSymbols() {return functions;}
|
||||||
|
|
||||||
|
// deprecated
|
||||||
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
||||||
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
||||||
XFuncMap::iterator End() { return functions.end(); }
|
XFuncMap::iterator End() { return functions.end(); }
|
||||||
|
|
||||||
|
const char *GetDescription(u32 addr);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void List();
|
void List();
|
||||||
|
void Index();
|
||||||
void FillInCallers();
|
void FillInCallers();
|
||||||
|
|
||||||
|
bool LoadMap(const char *filename);
|
||||||
|
bool SaveMap(const char *filename);
|
||||||
|
|
||||||
void PrintCalls(u32 funcAddr);
|
void PrintCalls(u32 funcAddr);
|
||||||
void PrintCallers(u32 funcAddr);
|
void PrintCallers(u32 funcAddr);
|
||||||
void LogFunctionCall(u32 addr);
|
void LogFunctionCall(u32 addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FunctionDB g_funcDB;
|
extern SymbolDB g_symbolDB;
|
@ -58,7 +58,7 @@ files = ["Console.cpp",
|
|||||||
"PowerPC/PPCAnalyst.cpp",
|
"PowerPC/PPCAnalyst.cpp",
|
||||||
"PowerPC/PPCTables.cpp",
|
"PowerPC/PPCTables.cpp",
|
||||||
"PowerPC/SignatureDB.cpp",
|
"PowerPC/SignatureDB.cpp",
|
||||||
"PowerPC/FunctionDB.cpp",
|
"PowerPC/SymbolDB.cpp",
|
||||||
"PowerPC/Interpreter/Interpreter.cpp",
|
"PowerPC/Interpreter/Interpreter.cpp",
|
||||||
"PowerPC/Interpreter/Interpreter_Branch.cpp",
|
"PowerPC/Interpreter/Interpreter_Branch.cpp",
|
||||||
"PowerPC/Interpreter/Interpreter_Integer.cpp",
|
"PowerPC/Interpreter/Interpreter_Integer.cpp",
|
||||||
|
@ -499,6 +499,54 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\src\CodeWindow.cpp"
|
RelativePath=".\src\CodeWindow.cpp"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|x64"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|x64"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="DebugFast|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="DebugFast|x64"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\CodeWindow.h"
|
RelativePath=".\src\CodeWindow.h"
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "BreakpointView.h"
|
#include "BreakpointView.h"
|
||||||
#include "Debugger/Debugger_BreakPoints.h"
|
#include "Debugger/Debugger_BreakPoints.h"
|
||||||
#include "Debugger/Debugger_SymbolMap.h"
|
#include "Debugger/Debugger_SymbolMap.h"
|
||||||
|
#include "PowerPC/SymbolDB.h"
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(CBreakPointView, wxListCtrl)
|
BEGIN_EVENT_TABLE(CBreakPointView, wxListCtrl)
|
||||||
|
|
||||||
@ -35,8 +36,7 @@ CBreakPointView::CBreakPointView(wxWindow* parent, const wxWindowID id, const wx
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void CBreakPointView::Update()
|
||||||
CBreakPointView::Update()
|
|
||||||
{
|
{
|
||||||
ClearAll();
|
ClearAll();
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ CBreakPointView::Update()
|
|||||||
|
|
||||||
char szBuffer[64];
|
char szBuffer[64];
|
||||||
const CBreakPoints::TBreakPoints& rBreakPoints = CBreakPoints::GetBreakPoints();
|
const CBreakPoints::TBreakPoints& rBreakPoints = CBreakPoints::GetBreakPoints();
|
||||||
for (size_t i=0; i<rBreakPoints.size(); i++)
|
for (size_t i = 0; i < rBreakPoints.size(); i++)
|
||||||
{
|
{
|
||||||
const TBreakPoint& rBP = rBreakPoints[i];
|
const TBreakPoint& rBP = rBreakPoints[i];
|
||||||
if (!rBP.bTemporary)
|
if (!rBP.bTemporary)
|
||||||
@ -59,10 +59,10 @@ CBreakPointView::Update()
|
|||||||
temp = wxString::FromAscii("BP");
|
temp = wxString::FromAscii("BP");
|
||||||
SetItem(Item, 1, temp);
|
SetItem(Item, 1, temp);
|
||||||
|
|
||||||
Debugger::XSymbolIndex index = Debugger::FindSymbol(rBP.iAddress);
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rBP.iAddress);
|
||||||
if (index > 0)
|
if (symbol)
|
||||||
{
|
{
|
||||||
temp = wxString::FromAscii(Debugger::GetDescription(rBP.iAddress));
|
temp = wxString::FromAscii("halloj"); //Debugger::GetDescription(rBP.iAddress));
|
||||||
SetItem(Item, 2, temp);
|
SetItem(Item, 2, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ CBreakPointView::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CBreakPoints::TMemChecks& rMemChecks = CBreakPoints::GetMemChecks();
|
const CBreakPoints::TMemChecks& rMemChecks = CBreakPoints::GetMemChecks();
|
||||||
for (size_t i=0; i<rMemChecks.size(); i++)
|
for (size_t i = 0; i < rMemChecks.size(); i++)
|
||||||
{
|
{
|
||||||
const TMemCheck& rMemCheck = rMemChecks[i];
|
const TMemCheck& rMemCheck = rMemChecks[i];
|
||||||
|
|
||||||
@ -85,10 +85,10 @@ CBreakPointView::Update()
|
|||||||
temp = wxString::FromAscii("MC");
|
temp = wxString::FromAscii("MC");
|
||||||
SetItem(Item, 1, temp);
|
SetItem(Item, 1, temp);
|
||||||
|
|
||||||
Debugger::XSymbolIndex index = Debugger::FindSymbol(rMemCheck.StartAddress);
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rMemCheck.StartAddress);
|
||||||
if (index > 0)
|
if (symbol)
|
||||||
{
|
{
|
||||||
temp = wxString::FromAscii(Debugger::GetDescription(rMemCheck.StartAddress));
|
temp = wxString::FromAscii("bjorn"); //Debugger::GetDescription(rMemCheck.StartAddress));
|
||||||
SetItem(Item, 2, temp);
|
SetItem(Item, 2, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
#include "Debugger/PPCDebugInterface.h"
|
#include "Debugger/PPCDebugInterface.h"
|
||||||
#include "Debugger/Debugger_SymbolMap.h"
|
#include "PowerPC/SymbolDB.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
|
||||||
@ -184,13 +184,13 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
|||||||
break;
|
break;
|
||||||
case IDM_COPYFUNCTION:
|
case IDM_COPYFUNCTION:
|
||||||
{
|
{
|
||||||
int sel = Debugger::FindSymbol(selection);
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(selection);
|
||||||
if (sel > 0) {
|
if (symbol) {
|
||||||
std::string text;
|
std::string text;
|
||||||
text = text + Debugger::GetSymbol(sel).GetName() + "\r\n";
|
text = text + symbol->name + "\r\n";
|
||||||
// we got a function
|
// we got a function
|
||||||
u32 start = Debugger::GetSymbol(sel).vaddress;
|
u32 start = symbol->address;
|
||||||
u32 end = start + Debugger::GetSymbol(sel).size;
|
u32 end = start + symbol->size;
|
||||||
for (u32 addr = start; addr != end; addr += 4) {
|
for (u32 addr = start; addr != end; addr += 4) {
|
||||||
text = text + StringFromFormat("%08x: ", addr) + debugger->disasm(addr) + "\r\n";
|
text = text + StringFromFormat("%08x: ", addr) + debugger->disasm(addr) + "\r\n";
|
||||||
}
|
}
|
||||||
@ -217,11 +217,12 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
|||||||
|
|
||||||
case IDM_RENAMESYMBOL:
|
case IDM_RENAMESYMBOL:
|
||||||
{
|
{
|
||||||
int sel = Debugger::FindSymbol(selection);
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(selection);
|
||||||
if (sel > 0) {
|
if (symbol) {
|
||||||
wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"), wxGetTextFromUserPromptStr, wxString::FromAscii(Debugger::GetSymbol(sel).GetName().c_str()));
|
wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"), wxGetTextFromUserPromptStr,
|
||||||
|
wxString::FromAscii(symbol->name.c_str()));
|
||||||
if (input_symbol.ShowModal() == wxID_OK) {
|
if (input_symbol.ShowModal() == wxID_OK) {
|
||||||
Debugger::AccessSymbol(sel).SetName(input_symbol.GetValue().mb_str());
|
symbol->name = input_symbol.GetValue().mb_str();
|
||||||
}
|
}
|
||||||
// redraw();
|
// redraw();
|
||||||
Host_NotifyMapLoaded();
|
Host_NotifyMapLoaded();
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
#include "Debugger/PPCDebugInterface.h"
|
#include "Debugger/PPCDebugInterface.h"
|
||||||
#include "Debugger/Debugger_SymbolMap.h"
|
#include "Debugger/Debugger_SymbolMap.h"
|
||||||
#include "PowerPC/PPCAnalyst.h"
|
#include "PowerPC/PPCAnalyst.h"
|
||||||
#include "PowerPC/FunctionDB.h"
|
#include "PowerPC/SymbolDB.h"
|
||||||
#include "PowerPC/SignatureDB.h"
|
#include "PowerPC/SignatureDB.h"
|
||||||
#include "PowerPC/PPCTables.h"
|
#include "PowerPC/PPCTables.h"
|
||||||
#include "PowerPC/Jit64/Jit.h"
|
#include "PowerPC/Jit64/Jit.h"
|
||||||
@ -73,6 +73,8 @@ BEGIN_EVENT_TABLE(CCodeWindow, wxFrame)
|
|||||||
EVT_MENU(IDM_BREAKPOINTWINDOW, CCodeWindow::OnToggleBreakPointWindow)
|
EVT_MENU(IDM_BREAKPOINTWINDOW, CCodeWindow::OnToggleBreakPointWindow)
|
||||||
EVT_MENU(IDM_MEMORYWINDOW, CCodeWindow::OnToggleMemoryWindow)
|
EVT_MENU(IDM_MEMORYWINDOW, CCodeWindow::OnToggleMemoryWindow)
|
||||||
|
|
||||||
|
EVT_MENU(IDM_CLEARSYMBOLS, CCodeWindow::OnSymbolsMenu)
|
||||||
|
EVT_MENU(IDM_LOADMAPFILE, CCodeWindow::OnSymbolsMenu)
|
||||||
EVT_MENU(IDM_SCANFUNCTIONS, CCodeWindow::OnSymbolsMenu)
|
EVT_MENU(IDM_SCANFUNCTIONS, CCodeWindow::OnSymbolsMenu)
|
||||||
EVT_MENU(IDM_SAVEMAPFILE, CCodeWindow::OnSymbolsMenu)
|
EVT_MENU(IDM_SAVEMAPFILE, CCodeWindow::OnSymbolsMenu)
|
||||||
EVT_MENU(IDM_CREATESIGNATUREFILE, CCodeWindow::OnSymbolsMenu)
|
EVT_MENU(IDM_CREATESIGNATUREFILE, CCodeWindow::OnSymbolsMenu)
|
||||||
@ -173,12 +175,13 @@ void CCodeWindow::CreateGUIControls(const SCoreStartupParameter& _LocalCoreStart
|
|||||||
|
|
||||||
DebugInterface* di = new PPCDebugInterface();
|
DebugInterface* di = new PPCDebugInterface();
|
||||||
|
|
||||||
sizerLeft->Add(callstack = new wxListBox(this, IDM_CALLSTACKLIST, wxDefaultPosition, wxSize(90, 100)), 0, wxEXPAND);
|
|
||||||
sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(90, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
|
|
||||||
codeview = new CCodeView(di, this, wxID_ANY);
|
codeview = new CCodeView(di, this, wxID_ANY);
|
||||||
sizerBig->Add(sizerLeft, 2, wxEXPAND);
|
sizerBig->Add(sizerLeft, 2, wxEXPAND);
|
||||||
sizerBig->Add(codeview, 5, wxEXPAND);
|
sizerBig->Add(codeview, 5, wxEXPAND);
|
||||||
|
|
||||||
|
sizerLeft->Add(callstack = new wxListBox(this, IDM_CALLSTACKLIST, wxDefaultPosition, wxSize(90, 100)), 0, wxEXPAND);
|
||||||
|
sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(90, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
|
||||||
|
|
||||||
SetSizer(sizerBig);
|
SetSizer(sizerBig);
|
||||||
|
|
||||||
sizerLeft->SetSizeHints(this);
|
sizerLeft->SetSizeHints(this);
|
||||||
@ -246,7 +249,10 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
|
|||||||
|
|
||||||
{
|
{
|
||||||
wxMenu *pSymbolsMenu = new wxMenu;
|
wxMenu *pSymbolsMenu = new wxMenu;
|
||||||
pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _T("&Load/generate symbol map"));
|
pSymbolsMenu->Append(IDM_CLEARSYMBOLS, _T("&Clear symbols"));
|
||||||
|
pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _T("&Generate symbol map"));
|
||||||
|
pSymbolsMenu->AppendSeparator();
|
||||||
|
pSymbolsMenu->Append(IDM_LOADMAPFILE, _T("&Load symbol map"));
|
||||||
pSymbolsMenu->Append(IDM_SAVEMAPFILE, _T("&Save symbol map"));
|
pSymbolsMenu->Append(IDM_SAVEMAPFILE, _T("&Save symbol map"));
|
||||||
pSymbolsMenu->AppendSeparator();
|
pSymbolsMenu->AppendSeparator();
|
||||||
pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _T("&Create signature file..."));
|
pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _T("&Create signature file..."));
|
||||||
@ -305,23 +311,34 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
|||||||
std::string mapfile = CBoot::GenerateMapFilename();
|
std::string mapfile = CBoot::GenerateMapFilename();
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
{
|
{
|
||||||
|
case IDM_CLEARSYMBOLS:
|
||||||
|
g_symbolDB.Clear();
|
||||||
|
Host_NotifyMapLoaded();
|
||||||
|
break;
|
||||||
case IDM_SCANFUNCTIONS:
|
case IDM_SCANFUNCTIONS:
|
||||||
|
{
|
||||||
|
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
|
||||||
|
SignatureDB db;
|
||||||
|
if (db.Load("data/totaldb.dsy"))
|
||||||
|
db.Apply(&g_symbolDB);
|
||||||
|
Host_NotifyMapLoaded();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IDM_LOADMAPFILE:
|
||||||
if (!File::Exists(mapfile))
|
if (!File::Exists(mapfile))
|
||||||
{
|
{
|
||||||
g_funcDB.Clear();
|
g_symbolDB.Clear();
|
||||||
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_funcDB);
|
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
|
||||||
SignatureDB db;
|
SignatureDB db;
|
||||||
if (db.Load("data/totaldb.dsy"))
|
if (db.Load("data/totaldb.dsy"))
|
||||||
db.Apply(&g_funcDB);
|
db.Apply(&g_symbolDB);
|
||||||
Debugger::GetFromAnalyzer();
|
|
||||||
} else {
|
} else {
|
||||||
Debugger::LoadSymbolMap(mapfile.c_str());
|
g_symbolDB.LoadMap(mapfile.c_str());
|
||||||
Debugger::PushMapToFunctionDB(&g_funcDB);
|
|
||||||
}
|
}
|
||||||
Host_NotifyMapLoaded();
|
Host_NotifyMapLoaded();
|
||||||
break;
|
break;
|
||||||
case IDM_SAVEMAPFILE:
|
case IDM_SAVEMAPFILE:
|
||||||
Debugger::SaveSymbolMap(mapfile.c_str());
|
g_symbolDB.SaveMap(mapfile.c_str());
|
||||||
break;
|
break;
|
||||||
case IDM_CREATESIGNATUREFILE:
|
case IDM_CREATESIGNATUREFILE:
|
||||||
{
|
{
|
||||||
@ -331,7 +348,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
|||||||
this);
|
this);
|
||||||
if (path) {
|
if (path) {
|
||||||
SignatureDB db;
|
SignatureDB db;
|
||||||
db.Initialize(&g_funcDB);
|
db.Initialize(&g_symbolDB);
|
||||||
std::string filename(path.ToAscii()); // PPCAnalyst::SaveSignatureDB(
|
std::string filename(path.ToAscii()); // PPCAnalyst::SaveSignatureDB(
|
||||||
db.Save(path.ToAscii());
|
db.Save(path.ToAscii());
|
||||||
}
|
}
|
||||||
@ -346,9 +363,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
|||||||
if (path) {
|
if (path) {
|
||||||
SignatureDB db;
|
SignatureDB db;
|
||||||
db.Load(path.ToAscii());
|
db.Load(path.ToAscii());
|
||||||
db.Apply(&g_funcDB);
|
db.Apply(&g_symbolDB);
|
||||||
Debugger::Reset();
|
|
||||||
Debugger::GetFromAnalyzer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Host_NotifyMapLoaded();
|
Host_NotifyMapLoaded();
|
||||||
@ -426,7 +441,6 @@ void CCodeWindow::OnAddrBoxChange(wxCommandEvent& event)
|
|||||||
void CCodeWindow::Update()
|
void CCodeWindow::Update()
|
||||||
{
|
{
|
||||||
codeview->Refresh();
|
codeview->Refresh();
|
||||||
|
|
||||||
callstack->Clear();
|
callstack->Clear();
|
||||||
|
|
||||||
std::vector<Debugger::CallstackEntry> stack;
|
std::vector<Debugger::CallstackEntry> stack;
|
||||||
@ -445,7 +459,6 @@ void CCodeWindow::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateButtonStates();
|
UpdateButtonStates();
|
||||||
|
|
||||||
Host_UpdateLogDisplay();
|
Host_UpdateLogDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,18 +467,12 @@ void CCodeWindow::NotifyMapLoaded()
|
|||||||
{
|
{
|
||||||
symbols->Show(false); // hide it for faster filling
|
symbols->Show(false); // hide it for faster filling
|
||||||
symbols->Clear();
|
symbols->Clear();
|
||||||
#ifdef _WIN32
|
|
||||||
const Debugger::XVectorSymbol& syms = Debugger::AccessSymbols();
|
for (SymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); iter++)
|
||||||
|
|
||||||
for (int i = 0; i < (int)syms.size(); i++)
|
|
||||||
{
|
{
|
||||||
int idx = symbols->Append(syms[i].GetName().c_str());
|
int idx = symbols->Append(iter->second.name.c_str());
|
||||||
symbols->SetClientData(idx, (void*)&syms[i]);
|
symbols->SetClientData(idx, (void*)&iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
#endif
|
|
||||||
|
|
||||||
symbols->Show(true);
|
symbols->Show(true);
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
@ -508,11 +515,11 @@ void CCodeWindow::UpdateButtonStates()
|
|||||||
void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
|
void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
int index = symbols->GetSelection();
|
int index = symbols->GetSelection();
|
||||||
Debugger::Symbol* pSymbol = static_cast<Debugger::Symbol *>(symbols->GetClientData(index));
|
Symbol* pSymbol = static_cast<Symbol *>(symbols->GetClientData(index));
|
||||||
|
|
||||||
if (pSymbol != NULL)
|
if (pSymbol != NULL)
|
||||||
{
|
{
|
||||||
codeview->Center(pSymbol->vaddress);
|
codeview->Center(pSymbol->address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,9 @@ class CCodeWindow
|
|||||||
IDM_MEMORYWINDOW,
|
IDM_MEMORYWINDOW,
|
||||||
IDM_SCANFUNCTIONS,
|
IDM_SCANFUNCTIONS,
|
||||||
IDM_LOGINSTRUCTIONS,
|
IDM_LOGINSTRUCTIONS,
|
||||||
|
IDM_LOADMAPFILE,
|
||||||
IDM_SAVEMAPFILE,
|
IDM_SAVEMAPFILE,
|
||||||
|
IDM_CLEARSYMBOLS,
|
||||||
IDM_CREATESIGNATUREFILE,
|
IDM_CREATESIGNATUREFILE,
|
||||||
IDM_USESIGNATUREFILE,
|
IDM_USESIGNATUREFILE,
|
||||||
IDM_USESYMBOLFILE,
|
IDM_USESYMBOLFILE,
|
||||||
|
@ -49,7 +49,7 @@ CJitWindow *the_jit_window;
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IDM_REFRESH_LIST = 33350,
|
IDM_REFRESH_LIST = 23350,
|
||||||
IDM_PPC_BOX,
|
IDM_PPC_BOX,
|
||||||
IDM_X86_BOX,
|
IDM_X86_BOX,
|
||||||
IDM_NEXT,
|
IDM_NEXT,
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
|
||||||
#include "Debugger/PPCDebugInterface.h"
|
#include "Debugger/PPCDebugInterface.h"
|
||||||
#include "Debugger/Debugger_SymbolMap.h"
|
#include "PowerPC/SymbolDB.h"
|
||||||
|
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "LogManager.h"
|
#include "LogManager.h"
|
||||||
@ -148,18 +148,18 @@ void CMemoryWindow::NotifyMapLoaded()
|
|||||||
{
|
{
|
||||||
symbols->Show(false); // hide it for faster filling
|
symbols->Show(false); // hide it for faster filling
|
||||||
symbols->Clear();
|
symbols->Clear();
|
||||||
|
/*
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const Debugger::XVectorSymbol& syms = Debugger::AccessSymbols();
|
const FunctionDB::XFuncMap &syms = g_symbolDB.Symbols();
|
||||||
|
for (FuntionDB::XFuncMap::iterator iter = syms.begin(); iter != syms.end(); ++iter)
|
||||||
for (int i = 0; i < (int)syms.size(); i++)
|
|
||||||
{
|
{
|
||||||
int idx = symbols->Append(syms[i].GetName().c_str());
|
int idx = symbols->Append(iter->second.name.c_str());
|
||||||
symbols->SetClientData(idx, (void*)&syms[i]);
|
symbols->SetClientData(idx, (void*)&iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
symbols->Show(true);
|
symbols->Show(true);
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
@ -167,11 +167,11 @@ void CMemoryWindow::NotifyMapLoaded()
|
|||||||
void CMemoryWindow::OnSymbolListChange(wxCommandEvent& event)
|
void CMemoryWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
int index = symbols->GetSelection();
|
int index = symbols->GetSelection();
|
||||||
Debugger::Symbol* pSymbol = static_cast<Debugger::Symbol*>(symbols->GetClientData(index));
|
Symbol* pSymbol = static_cast<Symbol *>(symbols->GetClientData(index));
|
||||||
|
|
||||||
if (pSymbol != NULL)
|
if (pSymbol != NULL)
|
||||||
{
|
{
|
||||||
memview->Center(pSymbol->vaddress);
|
memview->Center(pSymbol->address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,9 @@
|
|||||||
|
|
||||||
#define FIFO_SIZE (1024*1024)
|
#define FIFO_SIZE (1024*1024)
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
|
||||||
FifoReader fifo;
|
FifoReader fifo;
|
||||||
|
|
||||||
|
// STATE_TO_SAVE
|
||||||
static u8 *videoBuffer;
|
static u8 *videoBuffer;
|
||||||
static int size = 0;
|
static int size = 0;
|
||||||
static int readptr = 0;
|
static int readptr = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user