Merge pull request #5459 from sepalani/code
PPCSymbolDB: Split SaveMap function
This commit is contained in:
commit
98b6446249
|
@ -388,90 +388,65 @@ bool PPCSymbolDB::LoadMap(const std::string& filename, bool bad)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================
|
// Save symbol map similar to CodeWarrior's map file
|
||||||
/* Save the map file and save a code file */
|
bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const
|
||||||
// ----------------
|
|
||||||
bool PPCSymbolDB::SaveMap(const std::string& filename, bool WithCodes) const
|
|
||||||
{
|
{
|
||||||
// Format the name for the codes version
|
File::IOFile f(filename, "w");
|
||||||
std::string mapFile = filename;
|
|
||||||
if (WithCodes)
|
|
||||||
mapFile = mapFile.substr(0, mapFile.find_last_of(".")) + "_code.map";
|
|
||||||
|
|
||||||
// Check size
|
|
||||||
const int wxYES_NO = 0x00000002 | 0x00000008;
|
|
||||||
if (functions.size() == 0)
|
|
||||||
{
|
|
||||||
if (!AskYesNo(
|
|
||||||
StringFromFormat(
|
|
||||||
"No symbol names are generated. Do you want to replace '%s' with a blank file?",
|
|
||||||
mapFile.c_str())
|
|
||||||
.c_str(),
|
|
||||||
"Confirm", wxYES_NO))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a file
|
|
||||||
File::IOFile f(mapFile, "w");
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// Write ".text" at the top
|
||||||
// Walk through every code row
|
fprintf(f.GetHandle(), ".text\n");
|
||||||
// -------------------------
|
|
||||||
fprintf(f.GetHandle(), ".text\n"); // Write ".text" at the top
|
// Write symbol address, size, virtual address, alignment, name
|
||||||
XFuncMap::const_iterator itr = functions.begin();
|
for (const auto& function : functions)
|
||||||
u32 LastAddress = 0x80004000;
|
|
||||||
std::string LastSymbolName;
|
|
||||||
while (itr != functions.end())
|
|
||||||
{
|
{
|
||||||
// Save a map file
|
const Symbol& symbol = function.second;
|
||||||
const Symbol& rSymbol = itr->second;
|
fprintf(f.GetHandle(), "%08x %08x %08x %i %s\n", symbol.address, symbol.size, symbol.address, 0,
|
||||||
if (!WithCodes)
|
symbol.name.c_str());
|
||||||
{
|
}
|
||||||
fprintf(f.GetHandle(), "%08x %08x %08x %i %s\n", rSymbol.address, rSymbol.size,
|
return true;
|
||||||
rSymbol.address, 0, rSymbol.name.c_str());
|
}
|
||||||
++itr;
|
|
||||||
|
// Save code map (won't work if Core is running)
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - Dolphin doesn't load back code maps
|
||||||
|
// - It's a custom code map format
|
||||||
|
bool PPCSymbolDB::SaveCodeMap(const std::string& filename) const
|
||||||
|
{
|
||||||
|
constexpr int SYMBOL_NAME_LIMIT = 30;
|
||||||
|
File::IOFile f(filename, "w");
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Write ".text" at the top
|
||||||
|
fprintf(f.GetHandle(), ".text\n");
|
||||||
|
|
||||||
|
u32 next_address = 0;
|
||||||
|
for (const auto& function : functions)
|
||||||
|
{
|
||||||
|
const Symbol& symbol = function.second;
|
||||||
|
|
||||||
|
// Skip functions which are inside bigger functions
|
||||||
|
if (symbol.address + symbol.size <= next_address)
|
||||||
|
{
|
||||||
|
// At least write the symbol name and address
|
||||||
|
fprintf(f.GetHandle(), "// %08x beginning of %s\n", symbol.address, symbol.name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the symbol full name
|
||||||
|
fprintf(f.GetHandle(), "\n%s:\n", symbol.name.c_str());
|
||||||
|
next_address = symbol.address + symbol.size;
|
||||||
|
|
||||||
|
// Write the code
|
||||||
|
for (u32 address = symbol.address; address < next_address; address += 4)
|
||||||
|
{
|
||||||
|
const std::string disasm = debugger->Disassemble(address);
|
||||||
|
fprintf(f.GetHandle(), "%08x %-*.*s %s\n", address, SYMBOL_NAME_LIMIT, SYMBOL_NAME_LIMIT,
|
||||||
|
symbol.name.c_str(), disasm.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a code file
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get the current and next address
|
|
||||||
LastAddress = rSymbol.address;
|
|
||||||
LastSymbolName = rSymbol.name;
|
|
||||||
++itr;
|
|
||||||
|
|
||||||
/* To make nice straight lines we fill out the name with spaces, we also cut off
|
|
||||||
all names longer than 25 letters */
|
|
||||||
std::string TempSym;
|
|
||||||
for (u32 i = 0; i < 25; i++)
|
|
||||||
{
|
|
||||||
if (i < LastSymbolName.size())
|
|
||||||
TempSym += LastSymbolName[i];
|
|
||||||
else
|
|
||||||
TempSym += " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// We currently skip the last block because we don't know how long it goes
|
|
||||||
int space;
|
|
||||||
if (itr != functions.end())
|
|
||||||
space = itr->second.address - LastAddress;
|
|
||||||
else
|
|
||||||
space = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < space; i += 4)
|
|
||||||
{
|
|
||||||
int Address = LastAddress + i;
|
|
||||||
|
|
||||||
std::string disasm = debugger->Disassemble(Address);
|
|
||||||
fprintf(f.GetHandle(), "%08x %i %20s %s\n", Address, 0, TempSym.c_str(), disasm.c_str());
|
|
||||||
}
|
|
||||||
// Write a blank line after each block
|
|
||||||
fprintf(f.GetHandle(), "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// ===========
|
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
// 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 PPCSymbolDB : public SymbolDB
|
class PPCSymbolDB : public SymbolDB
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
DebugInterface* debugger;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef void (*functionGetterCallback)(Symbol* f);
|
typedef void (*functionGetterCallback)(Symbol* f);
|
||||||
|
|
||||||
|
@ -36,11 +33,15 @@ public:
|
||||||
void FillInCallers();
|
void FillInCallers();
|
||||||
|
|
||||||
bool LoadMap(const std::string& filename, bool bad = false);
|
bool LoadMap(const std::string& filename, bool bad = false);
|
||||||
bool SaveMap(const std::string& filename, bool WithCodes = false) const;
|
bool SaveSymbolMap(const std::string& filename) const;
|
||||||
|
bool SaveCodeMap(const std::string& filename) const;
|
||||||
|
|
||||||
void PrintCalls(u32 funcAddr) const;
|
void PrintCalls(u32 funcAddr) const;
|
||||||
void PrintCallers(u32 funcAddr) const;
|
void PrintCallers(u32 funcAddr) const;
|
||||||
void LogFunctionCall(u32 addr);
|
void LogFunctionCall(u32 addr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DebugInterface* debugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PPCSymbolDB g_symbolDB;
|
extern PPCSymbolDB g_symbolDB;
|
||||||
|
|
|
@ -287,7 +287,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDM_SAVEMAPFILE:
|
case IDM_SAVEMAPFILE:
|
||||||
g_symbolDB.SaveMap(writable_map_file);
|
g_symbolDB.SaveSymbolMap(writable_map_file);
|
||||||
break;
|
break;
|
||||||
case IDM_SAVE_MAP_FILE_AS:
|
case IDM_SAVE_MAP_FILE_AS:
|
||||||
{
|
{
|
||||||
|
@ -297,11 +297,16 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
||||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this);
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this);
|
||||||
|
|
||||||
if (!path.IsEmpty())
|
if (!path.IsEmpty())
|
||||||
g_symbolDB.SaveMap(WxStrToStr(path));
|
g_symbolDB.SaveSymbolMap(WxStrToStr(path));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDM_SAVE_MAP_FILE_WITH_CODES:
|
case IDM_SAVE_MAP_FILE_WITH_CODES:
|
||||||
g_symbolDB.SaveMap(writable_map_file, true);
|
{
|
||||||
|
// Format the name for the codes version
|
||||||
|
const std::string path =
|
||||||
|
writable_map_file.substr(0, writable_map_file.find_last_of(".")) + "_code.map";
|
||||||
|
g_symbolDB.SaveCodeMap(path);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDM_RENAME_SYMBOLS:
|
case IDM_RENAME_SYMBOLS:
|
||||||
|
|
Loading…
Reference in New Issue