// Copyright (c) 2012- PPSSPP 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 or later versions. // 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 git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #ifdef _WIN32 #include #include #else #include #endif #include #include "../../Globals.h" #include "../../Core/MemMap.h" #include "SymbolMap.h" #include SymbolMap symbolMap; //need improvement static u32 hasher(u32 last, u32 value) { return __rotl(last,3) ^ value; } //#define BWLINKS // TODO: This should ignore immediates of many instructions, in order to be less sensitive. If it did, // this could work okay. static u32 ComputeHash(u32 start, u32 size) { u32 hash=0; for (unsigned int i=start; i>26) { case 18: { if (LK) //LK { u32 addr; if(AA) addr = SignExt26(LI << 2); else addr = ptr + SignExt26(LI << 2); int funNum = SymbolMap::GetSymbolNum(addr); if (funNum>=0) entries[funNum].backwardLinks.push_back(ptr); } break; } default: ; } ptr+=4; } } } } #endif } void SymbolMap::ResetSymbolMap() { #ifdef BWLINKS for (int i=0; i= addr) { if (address < addr + entry.size) { if (entries[i].type & symmask) return (int) i; else return -1; } } else break; } return -1; } char descriptionTemp[256]; char *SymbolMap::GetDescription(unsigned int address) { int fun = SymbolMap::GetSymbolNum(address); //if (address == entries[fun].vaddress) //{ if (fun!=-1) return entries[fun].name; else { sprintf(descriptionTemp, "(%08x)", address); return descriptionTemp; } //} //else // return ""; } #ifdef _WIN32 void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symmask) { ShowWindow(listbox,SW_HIDE); ListBox_ResetContent(listbox); //int style = GetWindowLong(listbox,GWL_STYLE); ListBox_AddString(listbox,"(0x80000000)"); ListBox_SetItemData(listbox,0,0x80000000); //ListBox_AddString(listbox,"(0x80002000)"); //ListBox_SetItemData(listbox,1,0x80002000); SendMessage(listbox, WM_SETREDRAW, FALSE, 0); SendMessage(listbox, LB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30); for (size_t i = 0; i < entries.size(); i++) { if (entries[i].type & symmask) { char temp[256]; sprintf(temp,"%s (%d)",entries[i].name,entries[i].size); int index = ListBox_AddString(listbox,temp); ListBox_SetItemData(listbox,index,entries[i].vaddress); } } SendMessage(listbox, WM_SETREDRAW, TRUE, 0); RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); ShowWindow(listbox,SW_SHOW); } void SymbolMap::FillSymbolComboBox(HWND listbox,SymbolType symmask) { ShowWindow(listbox,SW_HIDE); ComboBox_ResetContent(listbox); //int style = GetWindowLong(listbox,GWL_STYLE); ComboBox_AddString(listbox,"(0x02000000)"); ComboBox_SetItemData(listbox,0,0x02000000); //ListBox_AddString(listbox,"(0x80002000)"); //ListBox_SetItemData(listbox,1,0x80002000); SendMessage(listbox, WM_SETREDRAW, FALSE, 0); SendMessage(listbox, CB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30); for (size_t i = 0; i < entries.size(); i++) { if (entries[i].type & symmask) { char temp[256]; sprintf(temp,"%s (%d)",entries[i].name,entries[i].size); int index = ComboBox_AddString(listbox,temp); ComboBox_SetItemData(listbox,index,entries[i].vaddress); } } SendMessage(listbox, WM_SETREDRAW, TRUE, 0); RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); ShowWindow(listbox,SW_SHOW); } void SymbolMap::FillListBoxBLinks(HWND listbox, int num) { ListBox_ResetContent(listbox); int style = GetWindowLong(listbox,GWL_STYLE); MapEntry &e = entries[num]; #ifdef BWLINKS for (int i=0; i=0) return entries[num].runCount; else return 0; } // Load an elf with symbols, use SymbolMap::compilefuncsignaturesfile // to make a symbol map, load a dol or somethin without symbols, then apply // the map with SymbolMap::usefuncsignaturesfile. void SymbolMap::CompileFuncSignaturesFile(const char *filename) { // Store name,length,first instruction,hash into file FILE *f = fopen(filename, "w"); fprintf(f,"00000000\n"); int count=0; for (size_t i = 0; i < entries.size(); i++) { int size = entries[i].size; if (size >= 16 && entries[i].type == ST_FUNCTION) { u32 inst = Memory::Read_Instruction(entries[i].vaddress); //try to make a bigger number of different vals sometime if (inst != 0) { char temp[64]; strncpy(temp,entries[i].name,63); fprintf(f, "%08x\t%08x\t%08x\t%s\n", inst, size, ComputeHash(entries[i].vaddress,size), temp); count++; } } } fseek(f,0,SEEK_SET); fprintf(f,"%08x",count); fclose(f); } struct Sig { u32 inst; u32 size; u32 hash; char name[64]; Sig(){} Sig(u32 _inst, u32 _size, u32 _hash, char *_name) : inst(_inst), size(_size), hash(_hash) { strncpy(name,_name,63); } bool operator <(const Sig &other) const { return inst < other.inst; } }; std::vector sigs; typedef std::map Sigmap; Sigmap sigmap; void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) { sigs.clear(); //SymbolMap::ResetSymbolMap(); //#1: Read the signature file and put them in a fast data structure FILE *f = fopen(filename, "r"); int count; if (fscanf(f, "%08x\n", &count) != 1) count = 0; char name[256]; for (int a=0; asecond; while (true) { if (sig->inst != inst) break; u32 hash = ComputeHash(addr,sig->size); if (hash==sig->hash) { //MATCH!!!! MapEntry e; e.address=addr; e.size= sig->size; e.vaddress = addr; e.type=ST_FUNCTION; strcpy(e.name,sig->name); addr+=sig->size-4; //don't need to check function interior entries.push_back(e); break; } sig++; } } } //ensure code coloring even if symbols were loaded before SymbolMap::SortSymbols(); }