1 // Copyright (c) 2012- PPSSPP Project. 2 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, version 2.0 or later versions. 6 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License 2.0 for more details. 11 12 // A copy of the GPL 2.0 should have been included with the program. 13 // If not, see http://www.gnu.org/licenses/ 14 15 // Official git repository and contact information can be found at 16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. 17 18 #pragma once 19 20 #include "ppsspp_config.h" 21 #include <mutex> 22 #include "Common/CommonTypes.h" 23 #include "Core/Debugger/SymbolMap.h" 24 #include "Core/MIPS/MIPSAnalyst.h" 25 26 #if PPSSPP_ARCH(AMD64) 27 typedef u64 HashType; 28 #else 29 typedef u32 HashType; 30 #endif 31 32 enum DisassemblyLineType { DISTYPE_OPCODE, DISTYPE_MACRO, DISTYPE_DATA, DISTYPE_OTHER }; 33 34 struct DisassemblyLineInfo 35 { 36 DisassemblyLineType type; 37 MIPSAnalyst::MipsOpcodeInfo info; 38 std::string name; 39 std::string params; 40 u32 totalSize; 41 }; 42 43 enum LineType { LINE_UP, LINE_DOWN, LINE_RIGHT }; 44 45 struct BranchLine 46 { 47 u32 first; 48 u32 second; 49 LineType type; 50 int laneIndex; 51 52 bool operator<(const BranchLine& other) const 53 { 54 return first < other.first; 55 } 56 }; 57 58 class DisassemblyEntry 59 { 60 public: ~DisassemblyEntry()61 virtual ~DisassemblyEntry() { }; 62 virtual void recheck() = 0; 63 virtual int getNumLines() = 0; 64 virtual int getLineNum(u32 address, bool findStart) = 0; 65 virtual u32 getLineAddress(int line) = 0; 66 virtual u32 getTotalSize() = 0; 67 virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) = 0; getBranchLines(u32 start,u32 size,std::vector<BranchLine> & dest)68 virtual void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest) { }; 69 }; 70 71 class DisassemblyFunction: public DisassemblyEntry 72 { 73 public: 74 DisassemblyFunction(u32 _address, u32 _size); 75 ~DisassemblyFunction(); 76 void recheck() override; 77 int getNumLines() override; 78 int getLineNum(u32 address, bool findStart) override; 79 u32 getLineAddress(int line) override; getTotalSize()80 u32 getTotalSize() override { return size; }; 81 bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) override; 82 void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest) override; 83 84 private: 85 void generateBranchLines(); 86 void load(); 87 void clear(); 88 void addOpcodeSequence(u32 start, u32 end); 89 90 u32 address; 91 u32 size; 92 HashType hash; 93 std::vector<BranchLine> lines; 94 std::map<u32,DisassemblyEntry*> entries; 95 std::vector<u32> lineAddresses; 96 std::recursive_mutex lock_; 97 }; 98 99 class DisassemblyOpcode: public DisassemblyEntry 100 { 101 public: DisassemblyOpcode(u32 _address,int _num)102 DisassemblyOpcode(u32 _address, int _num): address(_address), num(_num) { }; ~DisassemblyOpcode()103 virtual ~DisassemblyOpcode() { }; recheck()104 void recheck() override { }; getNumLines()105 int getNumLines() override { return num; }; getLineNum(u32 address,bool findStart)106 int getLineNum(u32 address, bool findStart) override { return (address - this->address) / 4; }; getLineAddress(int line)107 u32 getLineAddress(int line) override { return address + line * 4; }; getTotalSize()108 u32 getTotalSize() override { return num * 4; }; 109 bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) override; 110 void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest) override; 111 112 private: 113 u32 address; 114 int num; 115 }; 116 117 118 class DisassemblyMacro: public DisassemblyEntry 119 { 120 public: DisassemblyMacro(u32 _address)121 DisassemblyMacro(u32 _address): address(_address) { }; ~DisassemblyMacro()122 virtual ~DisassemblyMacro() { }; 123 124 void setMacroLi(u32 _immediate, u8 _rt); 125 void setMacroMemory(std::string _name, u32 _immediate, u8 _rt, int _dataSize); 126 recheck()127 void recheck() override { }; getNumLines()128 int getNumLines() override { return 1; }; getLineNum(u32 address,bool findStart)129 int getLineNum(u32 address, bool findStart) override { return 0; }; getLineAddress(int line)130 u32 getLineAddress(int line) override { return address; }; getTotalSize()131 u32 getTotalSize() override { return numOpcodes * 4; }; 132 bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) override; 133 private: 134 enum MacroType { MACRO_LI, MACRO_MEMORYIMM }; 135 136 MacroType type; 137 std::string name; 138 u32 immediate; 139 u32 address; 140 u32 numOpcodes; 141 u8 rt; 142 int dataSize; 143 }; 144 145 146 class DisassemblyData: public DisassemblyEntry 147 { 148 public: 149 DisassemblyData(u32 _address, u32 _size, DataType _type); ~DisassemblyData()150 virtual ~DisassemblyData() { }; 151 152 void recheck() override; getNumLines()153 int getNumLines() override { return (int)lines.size(); }; 154 int getLineNum(u32 address, bool findStart) override; getLineAddress(int line)155 u32 getLineAddress(int line) override { return lineAddresses[line]; }; getTotalSize()156 u32 getTotalSize() override { return size; }; 157 bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) override; 158 159 private: 160 void createLines(); 161 162 struct DataEntry 163 { 164 std::string text; 165 u32 size; 166 int lineNum; 167 }; 168 169 u32 address; 170 u32 size; 171 HashType hash; 172 DataType type; 173 std::map<u32,DataEntry> lines; 174 std::vector<u32> lineAddresses; 175 std::recursive_mutex lock_; 176 }; 177 178 class DisassemblyComment: public DisassemblyEntry 179 { 180 public: 181 DisassemblyComment(u32 _address, u32 _size, std::string name, std::string param); ~DisassemblyComment()182 virtual ~DisassemblyComment() { }; 183 recheck()184 void recheck() override { }; getNumLines()185 int getNumLines() override { return 1; }; getLineNum(u32 address,bool findStart)186 int getLineNum(u32 address, bool findStart) override { return 0; }; getLineAddress(int line)187 u32 getLineAddress(int line) override { return address; }; getTotalSize()188 u32 getTotalSize() override { return size; }; 189 bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols, DebugInterface *cpuDebug) override; 190 191 private: 192 u32 address; 193 u32 size; 194 std::string name; 195 std::string param; 196 }; 197 198 class DebugInterface; 199 200 class DisassemblyManager 201 { 202 public: 203 ~DisassemblyManager(); 204 205 void clear(); 206 setCpu(DebugInterface * _cpu)207 void setCpu(DebugInterface* _cpu) { cpu = _cpu; }; setMaxParamChars(int num)208 void setMaxParamChars(int num) { maxParamChars = num; clear(); }; 209 void getLine(u32 address, bool insertSymbols, DisassemblyLineInfo &dest, DebugInterface *cpuDebug = nullptr); 210 void analyze(u32 address, u32 size); 211 std::vector<BranchLine> getBranchLines(u32 start, u32 size); 212 213 u32 getStartAddress(u32 address); 214 u32 getNthPreviousAddress(u32 address, int n = 1); 215 u32 getNthNextAddress(u32 address, int n = 1); 216 getCpu()217 static DebugInterface* getCpu() { return cpu; }; getMaxParamChars()218 static int getMaxParamChars() { return maxParamChars; }; 219 private: 220 static std::map<u32,DisassemblyEntry*> entries; 221 static std::recursive_mutex entriesLock_; 222 static DebugInterface* cpu; 223 static int maxParamChars; 224 }; 225 226 bool isInInterval(u32 start, u32 size, u32 value); 227 bool IsLikelyStringAt(uint32_t addr); 228