From e246aaf419c34e23e6c37013e0b7ed7dbf11ba21 Mon Sep 17 00:00:00 2001 From: CarlKenner Date: Mon, 15 Dec 2014 10:13:45 +1030 Subject: [PATCH] Add "Load bad map file" option for map files on disc that don't quite match. Currently it is very simple and naive, but filters out most of the bad matches. --- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 95 +++++++++++++++++++ Source/Core/Core/PowerPC/PPCSymbolDB.h | 1 + Source/Core/DolphinWX/Debugger/CodeWindow.cpp | 1 + .../Debugger/CodeWindowFunctions.cpp | 20 ++++ Source/Core/DolphinWX/DolphinWX.vcxproj.user | 8 +- Source/Core/DolphinWX/Globals.h | 2 +- 6 files changed, 125 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index 9afa79178a..1d6f5076ce 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -269,6 +269,101 @@ bool PPCSymbolDB::LoadMap(const std::string& filename) return true; } +// Carefully load map files that might not be from exactly the right version +bool PPCSymbolDB::LoadBadMap(const std::string& filename) +{ + File::IOFile f(filename, "r"); + if (!f) + return false; + + bool started = false; + int good_count = 0, bad_count = 0; + + char line[512]; + while (fgets(line, 512, f.GetHandle())) + { + if (strlen(line) < 4) + continue; + + char temp[256]; + sscanf(line, "%255s", 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]; + // some entries in the table have a function name followed by " (entry of " followed by a container name, followed by ")" + // instead of a space followed by a number followed by a space followed by a name + if (strlen(line) > 27 && line[27] != ' ' && strstr(line, "(entry of ")) + { + sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name); + } + else + { + sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &unknown, name); + } + + const char *namepos = strstr(line, name); + if (namepos != nullptr) //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) + { + vaddress |= 0x80000000; + // check for BLR before function + u32 opcode = Memory::Read_Instruction(vaddress - 4); + if (opcode == 0x4e800020) + { + // check for BLR at end of function + opcode = Memory::Read_Instruction(vaddress + size - 4); + if (opcode == 0x4e800020) + { + AddKnownSymbol(vaddress, size, name); // ST_FUNCTION + ++good_count; + } + else + { + ++bad_count; + } + } + else + { + ++bad_count; + } + } + } + + Index(); + PanicAlertT("Loaded %d good functions, ignored %d bad functions", good_count, bad_count); + return true; +} + // =================================================== /* Save the map file and save a code file */ diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.h b/Source/Core/Core/PowerPC/PPCSymbolDB.h index 09e01d13ed..a301721242 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.h +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.h @@ -35,6 +35,7 @@ public: void FillInCallers(); bool LoadMap(const std::string& filename); + bool LoadBadMap(const std::string& filename); bool SaveMap(const std::string& filename, bool WithCodes = false) const; void PrintCalls(u32 funcAddr) const; diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index fb69650567..822913d078 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -754,6 +754,7 @@ void CCodeWindow::UpdateButtonStates() GetMenuBar()->Enable(IDM_SAVEMAPFILE, Initialized); GetMenuBar()->Enable(IDM_LOADMAPFILEAS, Initialized); GetMenuBar()->Enable(IDM_SAVEMAPFILEAS, Initialized); + GetMenuBar()->Enable(IDM_LOADBADMAPFILE, Initialized); GetMenuBar()->Enable(IDM_SAVEMAPFILEWITHCODES, Initialized); GetMenuBar()->Enable(IDM_CREATESIGNATUREFILE, Initialized); GetMenuBar()->Enable(IDM_APPENDSIGNATUREFILE, Initialized); diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index cba74774da..b19d26fb74 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -155,8 +155,11 @@ void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar) _("Try to load this game's function names automatically - but doesn't check .map files stored on the disc image yet.")); pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map"), _("Save the function names for each address to a .map file in your user settings map folder, named after the title id.")); + pSymbolsMenu->AppendSeparator(); pSymbolsMenu->Append(IDM_LOADMAPFILEAS, _("Choose symbol map file to load..."), _("Load any .map file containing the function names and addresses for this game.")); + pSymbolsMenu->Append(IDM_LOADBADMAPFILE, _("Load &bad map file..."), + _("Try to load a .map file that might be from a slightly different version.")); pSymbolsMenu->Append(IDM_SAVEMAPFILEAS, _("Save symbol map &as..."), _("Save the function names and addresses for this game as a .map file. If you want to open it in IDA pro, use the .idc script.")); pSymbolsMenu->AppendSeparator(); @@ -301,6 +304,23 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) NotifyMapLoaded(); } break; + case IDM_LOADBADMAPFILE: + { + const wxString path = wxFileSelector( + _("Load bad map file"), File::GetUserPath(D_MAPS_IDX), + title_id_str + ".map", ".map", + "Dolphin Map File (*.map)|*.map|All files (*.*)|*.*", + wxFD_OPEN | wxFD_FILE_MUST_EXIST, this); + + if (!path.IsEmpty()) + { + g_symbolDB.LoadBadMap(WxStrToStr(path)); + Parent->StatusBarMessage("Loaded symbols from '%s'", path.c_str()); + } + HLE::PatchFunctions(); + NotifyMapLoaded(); + } + break; case IDM_SAVEMAPFILE: g_symbolDB.SaveMap(writable_map_file); break; diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj.user b/Source/Core/DolphinWX/DolphinWX.vcxproj.user index ff24062772..4f062ae3a8 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj.user +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj.user @@ -1,4 +1,4 @@ - + @@ -6,4 +6,10 @@ $(BinaryOutputDir) WindowsLocalDebugger + + -d + + + -d + \ No newline at end of file diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 3df4f95996..20eda941d8 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -214,7 +214,7 @@ enum // Symbols IDM_CLEARSYMBOLS, IDM_SCANFUNCTIONS, - IDM_LOADMAPFILE, IDM_LOADMAPFILEAS, + IDM_LOADMAPFILE, IDM_LOADMAPFILEAS, IDM_LOADBADMAPFILE, IDM_SAVEMAPFILE, IDM_SAVEMAPFILEWITHCODES, IDM_SAVEMAPFILEAS, IDM_CREATESIGNATUREFILE, IDM_APPENDSIGNATUREFILE,