├── deci3dbg.vcxproj.user ├── README.md ├── deci3dbg.vcxproj.filters ├── deci3dbg.sln ├── plugin.cpp ├── consts.h ├── deci3dbg.vcproj ├── debmod.h ├── deci3dbg.vcxproj └── debug.cpp /deci3dbg.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deci3dbg 2 | 3 | ----- 4 | 5 | Ida Pro debugger module for Playstation 3. 6 | 7 | More info [here](http://oct0xor.github.io/2014/05/30/deci3dbg/) 8 | 9 | Author: oct0xor 10 | 11 | Licensed under the GPLv2 license. -------------------------------------------------------------------------------- /deci3dbg.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {525a00d1-d801-4e59-8b89-2574bf9e603c} 6 | cpp;c;cxx;rc;def;r;odl;idl;hpj;bat 7 | 8 | 9 | {13e4669a-8ccd-400f-b903-a22176be339c} 10 | h;hpp;hxx;hm;inl 11 | 12 | 13 | {84f1e70d-144d-4993-8c3e-695275771696} 14 | ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /deci3dbg.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deci3dbg", "deci3dbg.vcxproj", "{8B9EEC53-D710-48D0-9761-1A799CB7039E}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Debug|x64 = Debug|x64 9 | Debug64|Win32 = Debug64|Win32 10 | Debug64|x64 = Debug64|x64 11 | Release|Win32 = Release|Win32 12 | Release|x64 = Release|x64 13 | Release64|Win32 = Release64|Win32 14 | Release64|x64 = Release64|x64 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug|Win32.Build.0 = Debug|Win32 19 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug|x64.ActiveCfg = Debug|x64 20 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug|x64.Build.0 = Debug|x64 21 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug64|Win32.ActiveCfg = Debug64|Win32 22 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug64|Win32.Build.0 = Debug64|Win32 23 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug64|x64.ActiveCfg = Debug64|Win32 24 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Debug64|x64.Build.0 = Debug64|Win32 25 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release|Win32.ActiveCfg = Release|Win32 26 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release|Win32.Build.0 = Release|Win32 27 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release|x64.ActiveCfg = Release|x64 28 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release|x64.Build.0 = Release|x64 29 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release64|Win32.ActiveCfg = Release64|Win32 30 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release64|Win32.Build.0 = Release64|Win32 31 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release64|x64.ActiveCfg = Release64|x64 32 | {8B9EEC53-D710-48D0-9761-1A799CB7039E}.Release64|x64.Build.0 = Release64|x64 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 oct0xor 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. 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 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | extern debugger_t debugger; 23 | 24 | static bool init_plugin(void); 25 | 26 | bool plugin_inited; 27 | 28 | //-------------------------------------------------------------------------- 29 | // Initialize debugger plugin 30 | static int idaapi init(void) 31 | { 32 | if (init_plugin()) 33 | { 34 | dbg = &debugger; 35 | plugin_inited = true; 36 | return PLUGIN_KEEP; 37 | } 38 | return PLUGIN_SKIP; 39 | } 40 | 41 | //-------------------------------------------------------------------------- 42 | // Terminate debugger plugin 43 | static void idaapi term(void) 44 | { 45 | if (plugin_inited) 46 | { 47 | //term_plugin(); 48 | plugin_inited = false; 49 | } 50 | } 51 | 52 | //-------------------------------------------------------------------------- 53 | // The plugin method - usually is not used for debugger plugins 54 | static void idaapi run(int /*arg*/) 55 | { 56 | 57 | } 58 | 59 | //-------------------------------------------------------------------------- 60 | // Initialize PPC debugger plugin 61 | static bool init_plugin(void) 62 | { 63 | if (ph.id != PLFM_PPC) 64 | return false; 65 | 66 | return true; 67 | } 68 | 69 | //-------------------------------------------------------------------------- 70 | char comment[] = "DECI3 debugger plugin by oct0xor."; 71 | 72 | char help[] = 73 | "DECI3 debugger plugin by oct0xor.\n" 74 | "\n" 75 | "This module lets you debug programs running in Playstation 3.\n"; 76 | 77 | 78 | //-------------------------------------------------------------------------- 79 | // 80 | // PLUGIN DESCRIPTION BLOCK 81 | // 82 | //-------------------------------------------------------------------------- 83 | plugin_t PLUGIN = 84 | { 85 | IDP_INTERFACE_VERSION, 86 | PLUGIN_DBG, // plugin flags 87 | init, // initialize 88 | 89 | term, // terminate. this pointer may be NULL. 90 | 91 | run, // invoke plugin 92 | 93 | comment, // long comment about the plugin 94 | // it could appear in the status line 95 | // or as a hint 96 | 97 | help, // multiline help about the plugin 98 | 99 | "DECI3 debugger plugin", // the preferred short name of the plugin 100 | 101 | "" // the preferred hotkey to run the plugin 102 | }; 103 | -------------------------------------------------------------------------------- /consts.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONSTS__ 2 | #define __CONSTS__ 3 | 4 | // 5 | // This file contains definition and consts shared among all debugger clients and servers 6 | // 7 | // 8 | 9 | #include 10 | 11 | #define TIMEOUT (1000/25) // in milliseconds, timeout for polling 12 | #define TIMEOUT_INFINITY -1 13 | 14 | // the idarpc_stream_struct_t structure is not defined. 15 | // it is used as an opaque type provided by the transport level. 16 | // the transport level defines its own local type for it. 17 | typedef struct idarpc_stream_struct_t idarpc_stream_t; 18 | 19 | // bidirectional codes (client <-> server) 20 | #define RPC_OK 0 // response: function call succeeded 21 | #define RPC_UNK 1 // response: unknown function code 22 | #define RPC_MEM 2 // response: no memory 23 | 24 | #define RPC_OPEN 3 // server->client: i'm ready, the very first packet 25 | 26 | #define RPC_EVENT 4 // server->client: debug event ready, followed by debug_event 27 | #define RPC_EVOK 5 // client->server: event processed (in response to RPC_EVENT) 28 | // we need EVOK to handle the situation when the debug 29 | // event was detected by the server during polling and 30 | // was sent to the client using RPC_EVENT but client has not received it yet 31 | // and requested GET_DEBUG_EVENT. In this case we should not 32 | // call remote_get_debug_event() but instead force the client 33 | // to use the event sent by RPC_EVENT. 34 | // In other words, if the server has sent RPC_EVENT but has not 35 | // received RPC_EVOK, it should fail all GET_DEBUG_EVENTS. 36 | 37 | // client->server codes 38 | #define RPC_INIT 10 39 | #define RPC_TERM 11 40 | #define RPC_GET_PROCESS_INFO 12 41 | #define RPC_START_PROCESS 13 42 | #define RPC_EXIT_PROCESS 14 43 | #define RPC_ATTACH_PROCESS 15 44 | #define RPC_DETACH_PROCESS 16 45 | #define RPC_GET_DEBUG_EVENT 17 46 | #define RPC_PREPARE_TO_PAUSE_PROCESS 18 47 | #define RPC_STOPPED_AT_DEBUG_EVENT 19 48 | #define RPC_CONTINUE_AFTER_EVENT 20 49 | #define RPC_TH_SUSPEND 21 50 | #define RPC_TH_CONTINUE 22 51 | #define RPC_TH_SET_STEP 23 52 | #define RPC_GET_MEMORY_INFO 24 53 | #define RPC_READ_MEMORY 25 54 | #define RPC_WRITE_MEMORY 26 55 | #define RPC_UPDATE_BPTS 27 56 | #define RPC_UPDATE_LOWCNDS 28 57 | #define RPC_EVAL_LOWCND 29 58 | #define RPC_ISOK_BPT 30 59 | #define RPC_READ_REGS 31 60 | #define RPC_WRITE_REG 32 61 | #define RPC_GET_SREG_BASE 33 62 | #define RPC_SET_EXCEPTION_INFO 34 63 | 64 | #define RPC_OPEN_FILE 35 65 | #define RPC_CLOSE_FILE 36 66 | #define RPC_READ_FILE 38 67 | #define RPC_WRITE_FILE 39 68 | #define RPC_IOCTL 40 // both client and the server may send this packet 69 | #define RPC_UPDATE_CALL_STACK 41 70 | #define RPC_APPCALL 42 71 | #define RPC_CLEANUP_APPCALL 43 72 | 73 | // server->client codes 74 | #define RPC_SET_DEBUG_NAMES 50 75 | #define RPC_SYNC_STUB 51 76 | #define RPC_ERROR 52 77 | #define RPC_MSG 53 78 | #define RPC_WARNING 54 79 | #define RPC_HANDLE_DEBUG_EVENT 55 80 | #define RPC_REPORT_IDC_ERROR 56 81 | 82 | #pragma pack(push, 1) 83 | 84 | struct PACKED rpc_packet_t 85 | { // fields are always sent in the network order 86 | uint32 length; // length of the packet (do not count length & code) 87 | uchar code; // function code 88 | }; 89 | CASSERT(sizeof(rpc_packet_t) == 5); 90 | #pragma pack(pop) 91 | 92 | // Error reporting functions 93 | class rpc_engine_t; 94 | AS_PRINTF(2, 0) void dmsg(rpc_engine_t *, const char *format, va_list va); 95 | AS_PRINTF(2, 0) void derror(rpc_engine_t *, const char *format, va_list va); 96 | AS_PRINTF(2, 0) void dwarning(rpc_engine_t *, const char *format, va_list va); 97 | AS_PRINTF(3, 0) ssize_t dvmsg(int code, rpc_engine_t *ud, const char *format, va_list va); 98 | 99 | // We use this to declare reporting functions with a given user data 100 | #define DECLARE_UD_REPORTING(fnc, rpc) \ 101 | AS_PRINTF(2, 3) void d##fnc(const char *format, ...) \ 102 | { \ 103 | va_list va; \ 104 | va_start(va, format); \ 105 | ::d##fnc(rpc, format, va); \ 106 | va_end(va); \ 107 | } 108 | 109 | error_t idaapi GetRegValue(idc_value_t *argv, idc_value_t *r); 110 | error_t idaapi SetRegValue(idc_value_t *argv, idc_value_t *r); 111 | void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm); 112 | 113 | // IDC function name that is exported by a debugger module 114 | // to allow scripts to send debugger commands 115 | #define IDC_SENDDBG_CMD "SendDbgCommand" 116 | #define IDC_READ_MSR "ReadMsr" 117 | #define IDC_WRITE_MSR "WriteMsr" 118 | 119 | // A macro to convert a pointer to ea_t without sign extension. 120 | #define EA_T(ptr) (ea_t)(size_t)(ptr) 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /deci3dbg.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 21 | 39 | 41 | 52 | 60 | 62 | 64 | 66 | 70 | 72 | 74 | 76 | 78 | 80 | 81 | 89 | 106 | 108 | 120 | 128 | 130 | 132 | 134 | 138 | 140 | 142 | 144 | 146 | 148 | 149 | 150 | 151 | 152 | 153 | 156 | 158 | 159 | 161 | 162 | 164 | 165 | 166 | 169 | 171 | 172 | 174 | 175 | 176 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /debmod.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUGGER_MODULE__ 2 | #define __DEBUGGER_MODULE__ 3 | 4 | // 5 | // 6 | // This is the base debmod_t class definition 7 | // From this class all debugger code must inherite and specialize 8 | // 9 | // Some OS specific functions must be implemented: 10 | // bool init_subsystem(); 11 | // bool term_subsystem(); 12 | // debmod_t *create_debug_session(); 13 | // int create_thread(thread_cb_t thread_cb, void *context); 14 | // 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "consts.h" 21 | 22 | extern debugger_t debugger; 23 | 24 | struct name_info_t 25 | { 26 | eavec_t addrs; 27 | qvector names; 28 | void clear(void) 29 | { 30 | addrs.clear(); 31 | names.clear(); 32 | } 33 | }; 34 | 35 | // Very simple class to store pending events 36 | enum queue_pos_t 37 | { 38 | IN_FRONT, 39 | IN_BACK 40 | }; 41 | 42 | struct eventlist_t : public std::deque 43 | { 44 | private: 45 | bool synced; 46 | public: 47 | // save a pending event 48 | void enqueue(const debug_event_t &ev, queue_pos_t pos) 49 | { 50 | if ( pos != IN_BACK ) 51 | push_front(ev); 52 | else 53 | push_back(ev); 54 | } 55 | 56 | // retrieve a pending event 57 | bool retrieve(debug_event_t *event) 58 | { 59 | if ( empty() ) 60 | return false; 61 | // get the first event and return it 62 | *event = front(); 63 | pop_front(); 64 | return true; 65 | } 66 | }; 67 | 68 | typedef int ioctl_handler_t( 69 | class rpc_engine_t *rpc, 70 | int fn, 71 | const void *buf, 72 | size_t size, 73 | void **poutbuf, 74 | ssize_t *poutsize); 75 | 76 | int send_ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize); 77 | int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); 78 | int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); 79 | void set_arm_thumb_modes(ea_t *addrs, int qty); 80 | 81 | // Main class to represent a debugger module 82 | class debmod_t 83 | { 84 | char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize); 85 | 86 | protected: 87 | typedef std::map regval_map_t; 88 | qstring input_file_path; 89 | qvector exceptions; 90 | name_info_t dn_names; 91 | // Pending events. currently used only to store 92 | // exceptions that happen while attaching 93 | eventlist_t events; 94 | // The last event received via a successful get_debug_event() 95 | debug_event_t last_event; 96 | 97 | // appcall contexts 98 | struct call_context_t 99 | { 100 | regvals_t saved_regs; 101 | ea_t sp; 102 | ea_t ctrl_ea; 103 | bool regs_spoiled; 104 | call_context_t() : sp(BADADDR), ctrl_ea(BADADDR), regs_spoiled(false) {} 105 | }; 106 | typedef qstack call_contexts_t; 107 | typedef std::map appcalls_t; 108 | appcalls_t appcalls; 109 | 110 | int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) 111 | { 112 | return ::send_ioctl(rpc, fn, buf, size, poutbuf, poutsize); 113 | } 114 | // If an IDC error occurs: we can not prepare an error message on the server 115 | // side because we do not have access to error strings (they are in ida.hlp). 116 | // We pass the error code to IDA (with eventual arguments) so it can prepare 117 | // a nice error message for the user 118 | void report_idc_error(ea_t ea, error_t code, ssize_t errval, const char *errprm) 119 | { 120 | return ::report_idc_error(rpc, ea, code, errval, errprm); 121 | } 122 | 123 | typedef std::map lowcnds_t; 124 | lowcnds_t cndmap; 125 | bool handling_lowcnd; 126 | bool evaluate_and_handle_lowcnd(debug_event_t *event); 127 | bool handle_lowcnd(lowcnd_t *lc, debug_event_t *event); 128 | 129 | // helper functions for programmatical single stepping 130 | virtual int dbg_perform_single_step(debug_event_t *event, const insn_t &cmd); 131 | virtual int dbg_freeze_threads_except(thid_t) { return 0; } 132 | virtual int dbg_thaw_threads_except(thid_t) { return 0; } 133 | int resume_app_and_get_event(debug_event_t *dev); 134 | 135 | public: 136 | int debugger_flags; // initialized by dbg_init() 137 | meminfo_vec_t old_areas; 138 | rpc_engine_t *rpc; 139 | bool debug_debugger; 140 | 141 | // Since 64-bit debuggers usually can debug 32-bit applications, we can not 142 | // rely on sizeof(ea_t) to detect the current address size. The following 143 | // variable should be used instead. It is initialized with 8 for 64-bit debuggers 144 | // but they should adjust it as soon as they learn that a 32-bit application 145 | // is being debugged. 146 | // For 32-bit debuggers it is initialized with 4. 147 | int addrsize; 148 | 149 | // indexes of sp and program counter registers. 150 | // Must be initialized by derived classes. 151 | int sp_idx, pc_idx; 152 | 153 | // Total number of registers. 154 | // Must be initialized by derived classes. 155 | int nregs; 156 | 157 | // Breakpoint code. 158 | // Must be initialized by derived classes. 159 | bytevec_t bpt_code; 160 | 161 | DECLARE_UD_REPORTING(msg, rpc); 162 | DECLARE_UD_REPORTING(warning, rpc); 163 | DECLARE_UD_REPORTING(error, rpc); 164 | 165 | // ----------------------------------- 166 | // Constructors and destructors 167 | // ----------------------------------- 168 | debmod_t(); 169 | virtual ~debmod_t() { cleanup(); } 170 | 171 | // ----------------------------------- 172 | // Debug names methods 173 | // ----------------------------------- 174 | void clear_debug_names(); 175 | name_info_t *get_debug_names(); 176 | void save_debug_name(ea_t ea, const char *name); 177 | int set_debug_names(); 178 | int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); 179 | int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); 180 | // ----------------------------------- 181 | // Utility methods 182 | // ----------------------------------- 183 | void cleanup(void); 184 | char *debug_event_str(const debug_event_t *ev); 185 | AS_PRINTF(2, 3) void debdeb(const char *format, ...); 186 | AS_PRINTF(2, 3) bool deberr(const char *format, ...); 187 | bool same_as_oldmemcfg(const meminfo_vec_t &areas); 188 | void save_oldmemcfg(const meminfo_vec_t &areas); 189 | bool continue_after_last_event(bool handled = true); 190 | lowcnd_t *get_failed_lowcnd(thid_t tid, ea_t ea); 191 | // ----------------------------------- 192 | // Shared methods 193 | // ----------------------------------- 194 | virtual bool check_input_file_crc32(uint32 orig_crc); 195 | virtual const exception_info_t *find_exception(int code); 196 | virtual bool get_exception_name(int code, char *buf, size_t bufsize); 197 | 198 | // ----------------------------------- 199 | // Methods to be implemented 200 | // ----------------------------------- 201 | virtual int idaapi dbg_init(bool _debug_debugger) = 0; 202 | virtual void idaapi dbg_term(void) = 0; 203 | virtual int idaapi dbg_process_get_info(int n, 204 | const char *input, 205 | process_info_t *info) = 0; 206 | virtual int idaapi dbg_detach_process(void) = 0; 207 | virtual int idaapi dbg_start_process(const char *path, 208 | const char *args, 209 | const char *startdir, 210 | int flags, 211 | const char *input_path, 212 | uint32 input_file_crc32) = 0; 213 | virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_msecs) = 0; 214 | virtual int idaapi dbg_attach_process(pid_t process_id, int event_id) = 0; 215 | virtual int idaapi dbg_prepare_to_pause_process(void) = 0; 216 | virtual int idaapi dbg_exit_process(void) = 0; 217 | virtual int idaapi dbg_continue_after_event(const debug_event_t *event) = 0; 218 | virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty); 219 | virtual void idaapi dbg_stopped_at_debug_event(void) = 0; 220 | virtual int idaapi dbg_thread_suspend(thid_t thread_id) = 0; 221 | virtual int idaapi dbg_thread_continue(thid_t thread_id) = 0; 222 | virtual int idaapi dbg_thread_set_step(thid_t thread_id) = 0; 223 | virtual int idaapi dbg_read_registers(thid_t thread_id, 224 | int clsmask, 225 | regval_t *values) = 0; 226 | virtual int idaapi dbg_write_register(thid_t thread_id, 227 | int reg_idx, 228 | const regval_t *value) = 0; 229 | virtual int idaapi dbg_thread_get_sreg_base(thid_t thread_id, 230 | int sreg_value, 231 | ea_t *ea) = 0; 232 | virtual ea_t idaapi map_address(ea_t ea, const regval_t *, int /* regnum */) { return ea; } 233 | virtual int idaapi dbg_get_memory_info(meminfo_vec_t &areas) = 0; 234 | virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size) = 0; 235 | virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size) = 0; 236 | virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) = 0; 237 | // for swbpts, len may be -1 (unknown size, for example arm/thumb mode) or bpt opcode length 238 | virtual int idaapi dbg_add_bpt(bpttype_t type, ea_t ea, int len) = 0; 239 | virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) = 0; 240 | virtual int idaapi dbg_update_bpts(update_bpt_info_t *bpts, int nadd, int ndel); 241 | virtual int idaapi dbg_update_lowcnds(const lowcnd_t *lowcnds, int nlowcnds); 242 | virtual int idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea); 243 | virtual int idaapi dbg_open_file(const char *file, uint32 *fsize, bool readonly) = 0; 244 | virtual void idaapi dbg_close_file(int fn) = 0; 245 | virtual ssize_t idaapi dbg_read_file(int fn, uint32 off, void *buf, size_t size) = 0; 246 | virtual ssize_t idaapi dbg_write_file(int fn, uint32 off, const void *buf, size_t size) = 0; 247 | virtual int idaapi handle_ioctl(int /*fn*/, const void* /*buf*/, size_t /*size*/, 248 | void** /*outbuf*/, ssize_t* /*outsize*/) { return 0; } 249 | virtual int idaapi get_system_specific_errno(void) const; // this code must be acceptable by winerr() 250 | virtual bool idaapi dbg_update_call_stack(thid_t, call_stack_t *) { return false; } 251 | virtual ea_t idaapi dbg_appcall( 252 | ea_t /*func_ea*/, 253 | thid_t /*tid*/, 254 | const struct func_type_info_t * /*fti*/, 255 | int /*nargs*/, 256 | const struct regobjs_t * /*regargs*/, 257 | struct relobj_t * /*stkargs*/, 258 | struct regobjs_t * /*retregs*/, 259 | qstring *errbuf, 260 | debug_event_t * /*event*/, 261 | int /*flags*/); 262 | virtual int idaapi dbg_cleanup_appcall(thid_t /*tid*/); 263 | virtual bool idaapi write_registers( 264 | thid_t /*tid*/, 265 | int /*start*/, 266 | int /*count*/, 267 | const regval_t * /*values*/, 268 | const int * /*indices*/ = NULL) { return false; } 269 | // finalize appcall stack image 270 | // input: stack image contains the return address at the beginning 271 | virtual int finalize_appcall_stack(call_context_t &, regval_map_t &, bytevec_t &) { return 0; } 272 | virtual bool should_stop_appcall(thid_t tid, const debug_event_t *event, ea_t ea); 273 | virtual bool preprocess_appcall_cleanup(thid_t, call_context_t &) { return true; } 274 | virtual int get_regidx(const char *regname, int *clsmask) = 0; 275 | }; 276 | 277 | // some functions, per OS implemented 278 | bool init_subsystem(); 279 | bool term_subsystem(); 280 | debmod_t *create_debug_session(); 281 | 282 | // processor specific init/term 283 | void processor_specific_init(void); 284 | void processor_specific_term(void); 285 | 286 | // perform an action on all existing debugger modules 287 | struct debmod_visitor_t 288 | { 289 | virtual int visit(debmod_t *debmod) = 0; 290 | }; 291 | int for_all_debuggers(debmod_visitor_t &v); 292 | 293 | extern debmod_t *idc_debmod; 294 | extern thid_t idc_thread; 295 | extern bool ignore_sigint; 296 | 297 | void lprintf(const char *format,...); 298 | bool lock_begin(); 299 | bool lock_end(); 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /deci3dbg.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug64 6 | Win32 7 | 8 | 9 | Debug64 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release64 22 | Win32 23 | 24 | 25 | Release64 26 | x64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | 39 | 40 | {8B9EEC53-D710-48D0-9761-1A799CB7039E} 41 | 42 | 43 | 44 | DynamicLibrary 45 | v120 46 | false 47 | MultiByte 48 | 49 | 50 | DynamicLibrary 51 | v120 52 | false 53 | MultiByte 54 | 55 | 56 | DynamicLibrary 57 | v120 58 | false 59 | MultiByte 60 | 61 | 62 | DynamicLibrary 63 | v120 64 | false 65 | MultiByte 66 | 67 | 68 | v120 69 | 70 | 71 | v120 72 | 73 | 74 | v120 75 | 76 | 77 | v120 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | <_ProjectFileVersion>11.0.50727.1 97 | 98 | 99 | .\Release\ 100 | .\Release\ 101 | false 102 | 103 | 104 | .\Release\ 105 | .\Release\ 106 | false 107 | 108 | 109 | .\Debug\ 110 | .\Debug\ 111 | false 112 | 113 | 114 | .\Debug\ 115 | .\Debug\ 116 | false 117 | 118 | 119 | 120 | MaxSpeed 121 | OnlyExplicitInline 122 | ..\..\include;%(AdditionalIncludeDirectories) 123 | NDEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 124 | true 125 | MultiThreaded 126 | true 127 | NotUsing 128 | .\Release/deci3dbg.pch 129 | .\Release/ 130 | .\Release/ 131 | .\Release/ 132 | Level3 133 | true 134 | Cdecl 135 | Default 136 | 137 | 138 | /export:PLUGIN %(AdditionalOptions) 139 | ida.lib;PS3TMAPI.lib;PS3TMAPIx64.lib;Ws2_32.lib;%(AdditionalDependencies) 140 | ..\..\..\plugins\deci3dbg.plw 141 | true 142 | ..\..\lib\x86_win_vc_32;lib;%(AdditionalLibraryDirectories) 143 | .\Release/deci3dbg.pdb 144 | .\Release/deci3dbg.lib 145 | MachineX86 146 | 147 | 148 | NDEBUG;%(PreprocessorDefinitions) 149 | true 150 | true 151 | Win32 152 | .\Release/deci3dbg.tlb 153 | 154 | 155 | 156 | NDEBUG;%(PreprocessorDefinitions) 157 | 0x0419 158 | 159 | 160 | 161 | 162 | MaxSpeed 163 | OnlyExplicitInline 164 | ..\..\include;%(AdditionalIncludeDirectories) 165 | NDEBUG;__NT__;__IDP__;__EA64__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 166 | true 167 | MultiThreaded 168 | true 169 | NotUsing 170 | .\Release/deci3dbg.pch 171 | .\Release/ 172 | .\Release/ 173 | .\Release/ 174 | Level3 175 | true 176 | Cdecl 177 | Default 178 | 179 | 180 | /export:PLUGIN %(AdditionalOptions) 181 | ida.lib;PS3TMAPI.lib;PS3TMAPIx64.lib;Ws2_32.lib;%(AdditionalDependencies) 182 | ..\..\..\plugins\deci3dbg.p64 183 | true 184 | ..\..\lib\x86_win_vc_64;lib;%(AdditionalLibraryDirectories) 185 | .\Release/deci3dbg.pdb 186 | .\Release/deci3dbg.lib 187 | MachineX86 188 | 189 | 190 | NDEBUG;%(PreprocessorDefinitions) 191 | true 192 | true 193 | Win32 194 | .\Release/deci3dbg.tlb 195 | 196 | 197 | 198 | 199 | NDEBUG;%(PreprocessorDefinitions) 200 | 0x0419 201 | 202 | 203 | 204 | 205 | Disabled 206 | ..\..\include;%(AdditionalIncludeDirectories) 207 | _DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 208 | EnableFastChecks 209 | MultiThreadedDebug 210 | NotUsing 211 | .\Debug/deci3dbg.pch 212 | .\Debug/ 213 | .\Debug/ 214 | .\Debug/ 215 | Level3 216 | true 217 | EditAndContinue 218 | Cdecl 219 | Default 220 | 221 | 222 | /export:PLUGIN %(AdditionalOptions) 223 | ida.lib;PS3TMAPI.lib;PS3TMAPIx64.lib;Ws2_32.lib;%(AdditionalDependencies) 224 | ..\..\..\plugins\deci3dbg.plw 225 | true 226 | ..\..\lib\x86_win_vc_32;lib;%(AdditionalLibraryDirectories) 227 | true 228 | .\Debug/deci3dbg.pdb 229 | .\Debug/deci3dbg.lib 230 | MachineX86 231 | 232 | 233 | _DEBUG;%(PreprocessorDefinitions) 234 | true 235 | true 236 | Win32 237 | .\Debug/deci3dbg.tlb 238 | 239 | 240 | 241 | _DEBUG;%(PreprocessorDefinitions) 242 | 0x0409 243 | 244 | 245 | 246 | 247 | Disabled 248 | ..\..\include;%(AdditionalIncludeDirectories) 249 | _DEBUG;__NT__;__IDP__;__EA64__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 250 | EnableFastChecks 251 | MultiThreadedDebug 252 | NotUsing 253 | .\Debug/deci3dbg.pch 254 | .\Debug/ 255 | .\Debug/ 256 | .\Debug/ 257 | Level3 258 | true 259 | EditAndContinue 260 | Cdecl 261 | Default 262 | 263 | 264 | /export:PLUGIN %(AdditionalOptions) 265 | ida.lib;PS3TMAPI.lib;PS3TMAPIx64.lib;Ws2_32.lib;%(AdditionalDependencies) 266 | ..\..\..\plugins\deci3dbg.p64 267 | true 268 | ..\..\lib\x86_win_vc_64;lib;%(AdditionalLibraryDirectories) 269 | true 270 | .\Debug/deci3dbg.pdb 271 | .\Debug/deci3dbg.lib 272 | MachineX86 273 | 274 | 275 | _DEBUG;%(PreprocessorDefinitions) 276 | true 277 | true 278 | Win32 279 | .\Debug/deci3dbg.tlb 280 | 281 | 282 | 283 | 284 | _DEBUG;%(PreprocessorDefinitions) 285 | 0x0409 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | -------------------------------------------------------------------------------- /debug.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 oct0xor 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. 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 | #define _WINSOCKAPI_ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "debmod.h" 36 | #include "include\ps3tmapi.h" 37 | 38 | #ifdef _DEBUG 39 | #define debug_printf msg 40 | #else 41 | #define debug_printf(...) 42 | #endif 43 | 44 | #define DEBUGGER_NAME "deci3" 45 | #define DEBUGGER_ID_PLAYSTATION_3 15 46 | #define PROCESSOR_NAME "ppc" 47 | 48 | static error_t idaapi idc_threadlst(idc_value_t *argv, idc_value_t *res); 49 | void get_threads_info(void); 50 | void clear_all_bp(uint32 tid); 51 | uint32 read_pc_register(uint32 tid); 52 | uint32 read_lr_register(uint32 tid); 53 | uint32 read_ctr_register(uint32 tid); 54 | int do_step(uint32 tid, uint32 dbg_notification); 55 | 56 | static const char idc_threadlst_args[] = {0}; 57 | 58 | std::vector Targets; 59 | std::string TargetName; 60 | HTARGET TargetID; 61 | uint32 ProcessID; 62 | 63 | bool LaunchTargetPicker = true; 64 | bool AlwaysDC = false; 65 | bool ForceDC = true; 66 | bool WasOriginallyConnected = false; 67 | 68 | static bool attaching = false; 69 | static bool singlestep = false; 70 | static bool continue_from_bp = false; 71 | static bool dabr_is_set = false; 72 | uint32 dabr_addr; 73 | uint8 dabr_type; 74 | 75 | eventlist_t events; 76 | SNPS3_DBG_EVENT_DATA target_event; 77 | 78 | std::unordered_map process_names; 79 | std::unordered_map modules; 80 | std::unordered_map main_bpts_map; 81 | 82 | std::vector step_bpts; 83 | std::vector main_bpts; 84 | 85 | static const unsigned char bpt_code[] = {0x7f, 0xe0, 0x00, 0x08}; 86 | 87 | #define STEP_INTO 15 88 | #define STEP_OVER 16 89 | 90 | #define RC_GENERAL 1 91 | #define RC_FLOAT 2 92 | //#define RC_VECTOR 3 93 | 94 | struct regval 95 | { 96 | uint64 lval; 97 | uint64 rval; 98 | }; 99 | typedef struct regval regval; 100 | 101 | //-------------------------------------------------------------------------- 102 | const char* register_classes[] = 103 | { 104 | "General registers", 105 | "Floating point registers", 106 | /*"Velocity Engine/VMX/AltiVec", // 128-bit Vector Registers*/ 107 | NULL 108 | }; 109 | 110 | static const char *const CReg[] = 111 | { 112 | "cr7", 113 | "cr7", 114 | "cr7", 115 | "cr7", 116 | "cr6", 117 | "cr6", 118 | "cr6", 119 | "cr6", 120 | "cr5", 121 | "cr5", 122 | "cr5", 123 | "cr5", 124 | "cr4", 125 | "cr4", 126 | "cr4", 127 | "cr4", 128 | "cr3", 129 | "cr3", 130 | "cr3", 131 | "cr3", 132 | "cr2", 133 | "cr2", 134 | "cr2", 135 | "cr2", 136 | "cr1", 137 | "cr1", 138 | "cr1", 139 | "cr1", 140 | "cr0", 141 | "cr0", 142 | "cr0", 143 | "cr0", 144 | NULL, 145 | NULL, 146 | NULL, 147 | NULL, 148 | NULL, 149 | NULL, 150 | NULL, 151 | NULL, 152 | NULL, 153 | NULL, 154 | NULL, 155 | NULL, 156 | NULL, 157 | NULL, 158 | NULL, 159 | NULL, 160 | NULL, 161 | NULL, 162 | NULL, 163 | NULL, 164 | NULL, 165 | NULL, 166 | NULL, 167 | NULL, 168 | NULL, 169 | NULL, 170 | NULL, 171 | NULL, 172 | NULL, 173 | NULL, 174 | NULL, 175 | NULL, 176 | }; 177 | 178 | static const char *const vmx_format[] = 179 | { 180 | "VMX 128 bit", 181 | }; 182 | 183 | //-------------------------------------------------------------------------- 184 | register_info_t registers[] = 185 | { 186 | { "r0", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 187 | { "r1", REGISTER_ADDRESS | REGISTER_SP, RC_GENERAL, dt_qword, NULL, 0 }, 188 | { "r2", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 189 | { "r3", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 190 | { "r4", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 191 | { "r5", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 192 | { "r6", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 193 | { "r7", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 194 | { "r8", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 195 | { "r9", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 196 | { "r10", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 197 | { "r11", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 198 | { "r12", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 199 | { "r13", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 200 | { "r14", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 201 | { "r15", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 202 | { "r16", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 203 | { "r17", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 204 | { "r18", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 205 | { "r19", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 206 | { "r20", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 207 | { "r21", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 208 | { "r22", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 209 | { "r23", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 210 | { "r24", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 211 | { "r25", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 212 | { "r26", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 213 | { "r27", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 214 | { "r28", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 215 | { "r29", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 216 | { "r30", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 217 | { "r31", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 218 | 219 | { "PC", REGISTER_ADDRESS | REGISTER_IP, RC_GENERAL, dt_qword, NULL, 0 }, 220 | { "CR", NULL, RC_GENERAL, dt_qword, CReg, 0xFFFFFFFF }, 221 | //{ "CR", NULL, RC_GENERAL, dt_qword, NULL, 0 }, 222 | { "LR", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 223 | { "CTR", REGISTER_ADDRESS, RC_GENERAL, dt_qword, NULL, 0 }, 224 | 225 | { "f0", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 226 | { "f1", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 227 | { "f2", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 228 | { "f3", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 229 | { "f4", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 230 | { "f5", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 231 | { "f6", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 232 | { "f7", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 233 | { "f8", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 234 | { "f9", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 235 | { "f10", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 236 | { "f11", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 237 | { "f12", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 238 | { "f13", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 239 | { "f14", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 240 | { "f15", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 241 | { "f16", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 242 | { "f17", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 243 | { "f18", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 244 | { "f19", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 245 | { "f20", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 246 | { "f21", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 247 | { "f22", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 248 | { "f23", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 249 | { "f24", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 250 | { "f25", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 251 | { "f26", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 252 | { "f27", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 253 | { "f28", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 254 | { "f29", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 255 | { "f30", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 256 | { "f31", NULL, RC_FLOAT, dt_qword, NULL, 0 }, 257 | 258 | /*{ "v0", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 259 | { "v1", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 260 | { "v2", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 261 | { "v3", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 262 | { "v4", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 263 | { "v5", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 264 | { "v6", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 265 | { "v7", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 266 | { "v8", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 267 | { "v9", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 268 | { "v10", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 269 | { "v11", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 270 | { "v12", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 271 | { "v13", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 272 | { "v14", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 273 | { "v15", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 274 | { "v16", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 275 | { "v17", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 276 | { "v18", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 277 | { "v19", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 278 | { "v20", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 279 | { "v21", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 280 | { "v22", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 281 | { "v23", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 282 | { "v24", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 283 | { "v25", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 284 | { "v26", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 285 | { "v27", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 286 | { "v28", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 287 | { "v29", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 288 | { "v30", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }, 289 | { "v31", REGISTER_CUSTFMT, RC_VECTOR, dt_byte16, vmx_format, 0 }*/ 290 | }; 291 | 292 | uint32 registers_id[68] = { 293 | SNPS3_gpr_0, 294 | SNPS3_gpr_1, 295 | SNPS3_gpr_2, 296 | SNPS3_gpr_3, 297 | SNPS3_gpr_4, 298 | SNPS3_gpr_5, 299 | SNPS3_gpr_6, 300 | SNPS3_gpr_7, 301 | SNPS3_gpr_8, 302 | SNPS3_gpr_9, 303 | SNPS3_gpr_10, 304 | SNPS3_gpr_11, 305 | SNPS3_gpr_12, 306 | SNPS3_gpr_13, 307 | SNPS3_gpr_14, 308 | SNPS3_gpr_15, 309 | SNPS3_gpr_16, 310 | SNPS3_gpr_17, 311 | SNPS3_gpr_18, 312 | SNPS3_gpr_19, 313 | SNPS3_gpr_20, 314 | SNPS3_gpr_21, 315 | SNPS3_gpr_22, 316 | SNPS3_gpr_23, 317 | SNPS3_gpr_24, 318 | SNPS3_gpr_25, 319 | SNPS3_gpr_26, 320 | SNPS3_gpr_27, 321 | SNPS3_gpr_28, 322 | SNPS3_gpr_29, 323 | SNPS3_gpr_30, 324 | SNPS3_gpr_31, 325 | 326 | SNPS3_pc, 327 | SNPS3_cr, 328 | SNPS3_lr, 329 | SNPS3_ctr, 330 | //SNPS3_xer // "XER" 331 | //SNPS3_fpscr // "fpscr" 332 | //SNPS3_vscr // "vscr" 333 | //SNPS3_vrsave // "vrsave" 334 | //SNPS3_msr // "msr" 335 | 336 | SNPS3_fpr_0, 337 | SNPS3_fpr_1, 338 | SNPS3_fpr_2, 339 | SNPS3_fpr_3, 340 | SNPS3_fpr_4, 341 | SNPS3_fpr_5, 342 | SNPS3_fpr_6, 343 | SNPS3_fpr_7, 344 | SNPS3_fpr_8, 345 | SNPS3_fpr_9, 346 | SNPS3_fpr_10, 347 | SNPS3_fpr_11, 348 | SNPS3_fpr_12, 349 | SNPS3_fpr_13, 350 | SNPS3_fpr_14, 351 | SNPS3_fpr_15, 352 | SNPS3_fpr_16, 353 | SNPS3_fpr_17, 354 | SNPS3_fpr_18, 355 | SNPS3_fpr_19, 356 | SNPS3_fpr_20, 357 | SNPS3_fpr_21, 358 | SNPS3_fpr_22, 359 | SNPS3_fpr_23, 360 | SNPS3_fpr_24, 361 | SNPS3_fpr_25, 362 | SNPS3_fpr_26, 363 | SNPS3_fpr_27, 364 | SNPS3_fpr_28, 365 | SNPS3_fpr_29, 366 | SNPS3_fpr_30, 367 | SNPS3_fpr_31, 368 | 369 | /*SNPS3_vmx_0, 370 | SNPS3_vmx_1, 371 | SNPS3_vmx_2, 372 | SNPS3_vmx_3, 373 | SNPS3_vmx_4, 374 | SNPS3_vmx_5, 375 | SNPS3_vmx_6, 376 | SNPS3_vmx_7, 377 | SNPS3_vmx_8, 378 | SNPS3_vmx_9, 379 | SNPS3_vmx_10, 380 | SNPS3_vmx_11, 381 | SNPS3_vmx_12, 382 | SNPS3_vmx_13, 383 | SNPS3_vmx_14, 384 | SNPS3_vmx_15, 385 | SNPS3_vmx_16, 386 | SNPS3_vmx_17, 387 | SNPS3_vmx_18, 388 | SNPS3_vmx_19, 389 | SNPS3_vmx_20, 390 | SNPS3_vmx_21, 391 | SNPS3_vmx_22, 392 | SNPS3_vmx_23, 393 | SNPS3_vmx_24, 394 | SNPS3_vmx_25, 395 | SNPS3_vmx_26, 396 | SNPS3_vmx_27, 397 | SNPS3_vmx_28, 398 | SNPS3_vmx_29, 399 | SNPS3_vmx_30, 400 | SNPS3_vmx_31*/ 401 | }; 402 | 403 | //------------------------------------------------------------------------- 404 | static inline uint32 bswap32(uint32 x) 405 | { 406 | return ( (x << 24) & 0xff000000 ) | 407 | ( (x << 8) & 0x00ff0000 ) | 408 | ( (x >> 8) & 0x0000ff00 ) | 409 | ( (x >> 24) & 0x000000ff ); 410 | } 411 | 412 | static inline uint64 bswap64(uint64 x) 413 | { 414 | return ( (x << 56) & 0xff00000000000000ULL ) | 415 | ( (x << 40) & 0x00ff000000000000ULL ) | 416 | ( (x << 24) & 0x0000ff0000000000ULL ) | 417 | ( (x << 8) & 0x000000ff00000000ULL ) | 418 | ( (x >> 8) & 0x00000000ff000000ULL ) | 419 | ( (x >> 24) & 0x0000000000ff0000ULL ) | 420 | ( (x >> 40) & 0x000000000000ff00ULL ) | 421 | ( (x >> 56) & 0x00000000000000ffULL ); 422 | } 423 | 424 | //------------------------------------------------------------------------- 425 | bool ConnectToActiveTarget() 426 | { 427 | char* pszUsage = NULL; 428 | SNRESULT snr; 429 | // Connect to the target. 430 | if (SN_FAILED(snr = SNPS3Connect(TargetID, NULL))) 431 | { 432 | if (snr == SN_E_TARGET_IN_USE && ForceDC) 433 | { 434 | if (SN_FAILED( snr = SNPS3ForceDisconnect(TargetID) )) 435 | { 436 | debug_printf("Unable to force disconnect %s\n", CUTF8ToWChar(pszUsage).c_str()); 437 | return false; 438 | } 439 | else 440 | { 441 | snr = SNPS3Connect(TargetID, NULL); 442 | } 443 | } 444 | 445 | if (SN_FAILED(snr)) 446 | { 447 | debug_printf("Failed to connect to target\n"); 448 | return false; 449 | } 450 | } 451 | else 452 | { 453 | WasOriginallyConnected = (snr == SN_S_NO_ACTION); 454 | } 455 | 456 | msg("Connected to target\n"); 457 | return true; 458 | } 459 | 460 | //------------------------------------------------------------------------- 461 | int __stdcall EnumCallBack(HTARGET hTarget) 462 | { 463 | SNPS3TargetInfo ti; 464 | std::auto_ptr pti(new SNPS3TargetInfo); 465 | 466 | if (pti.get()) 467 | { 468 | ti.hTarget = hTarget; 469 | ti.nFlags = SN_TI_TARGETID; 470 | 471 | if (SN_S_OK == SNPS3GetTargetInfo(&ti)) 472 | { 473 | // Store target parameters. 474 | pti->hTarget = hTarget; 475 | pti->pszName = _strdup(ti.pszName); 476 | pti->pszHomeDir = _strdup(ti.pszHomeDir); 477 | pti->pszFSDir = _strdup(ti.pszFSDir); 478 | 479 | // Store this target. 480 | Targets.push_back(pti.release()); 481 | } 482 | else 483 | { 484 | // Terminate enumeration. 485 | return 1; 486 | } 487 | } 488 | 489 | // Carry on with enumeration. 490 | return 0; 491 | } 492 | 493 | void SetTargetName(std::string targetName) 494 | { 495 | TargetName = targetName; 496 | } 497 | 498 | void SetTargetId(HTARGET hTargetId) 499 | { 500 | TargetID = hTargetId; 501 | } 502 | 503 | bool FindFirstConnectedTarget(void) 504 | { 505 | ECONNECTSTATUS nStatus = (ECONNECTSTATUS) -1; 506 | char* pszUsage = 0; 507 | 508 | std::vector::iterator iter = Targets.begin(); 509 | 510 | while (iter != Targets.end()) 511 | { 512 | SNRESULT snr = SNPS3GetConnectStatus((*iter)->hTarget, &nStatus, &pszUsage); 513 | 514 | if (SN_SUCCEEDED( snr )) 515 | { 516 | if (nStatus == CS_CONNECTED) 517 | { 518 | SNPS3TargetInfo ti; 519 | 520 | ti.hTarget = (*iter)->hTarget; 521 | ti.nFlags = SN_TI_TARGETID; 522 | 523 | if (SN_S_OK == SNPS3GetTargetInfo(&ti)) 524 | { 525 | // Store target parameters. 526 | SetTargetId(ti.hTarget); 527 | SetTargetName(ti.pszName); 528 | 529 | return true; 530 | } 531 | } 532 | } 533 | iter++; 534 | } 535 | 536 | return false; 537 | } 538 | 539 | bool FindFirstAvailableTarget(void) 540 | { 541 | uint nStatus = -1; 542 | char* pszUsage = 0; 543 | 544 | std::vector::iterator iter = Targets.begin(); 545 | 546 | while (iter != Targets.end()) 547 | { 548 | SNRESULT snr = SNPS3Connect((*iter)->hTarget, NULL); 549 | 550 | if (SN_SUCCEEDED( snr )) 551 | { 552 | SNPS3TargetInfo ti; 553 | 554 | ti.hTarget = (*iter)->hTarget; 555 | ti.nFlags = SN_TI_TARGETID; 556 | 557 | if (SN_S_OK == SNPS3GetTargetInfo(&ti)) 558 | { 559 | // Store target parameters. 560 | SetTargetId(ti.hTarget); 561 | SetTargetName(ti.pszName); 562 | return true; 563 | } 564 | } 565 | 566 | iter++; 567 | } 568 | 569 | return false; 570 | } 571 | 572 | bool GetHostnames(const char* input, std::string& ipOut, std::string& dnsNameOut) 573 | { 574 | WSADATA wsaData; 575 | int iResult; 576 | 577 | // Initialize Winsock 578 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 579 | if (iResult != 0) { 580 | return false; 581 | } 582 | 583 | sockaddr_in remotemachine; 584 | char hostname[NI_MAXHOST]; 585 | 586 | remotemachine.sin_family = AF_INET; 587 | remotemachine.sin_addr.s_addr = inet_addr(input); 588 | 589 | // IP->Hostname 590 | DWORD dwRetVal = getnameinfo((SOCKADDR *)&remotemachine, 591 | sizeof(sockaddr), 592 | hostname, 593 | NI_MAXHOST, 594 | NULL, 595 | 0, 596 | NI_NAMEREQD); 597 | 598 | if (dwRetVal == 0) 599 | { 600 | dnsNameOut = hostname; 601 | return true; 602 | } 603 | 604 | // Hostname -> IP 605 | struct hostent *remoteHost; 606 | remoteHost = gethostbyname(input); 607 | 608 | int i = 0; 609 | struct in_addr addr = { 0 }; 610 | if (remoteHost && remoteHost->h_addrtype == AF_INET) 611 | { 612 | if (remoteHost->h_addr_list[0] != 0) 613 | { 614 | addr.s_addr = *(u_long *) remoteHost->h_addr_list[0]; 615 | ipOut = inet_ntoa(addr); 616 | return true; 617 | } 618 | } 619 | 620 | WSACleanup(); 621 | return false; 622 | } 623 | 624 | bool GetTargetFromAddress(const char *pszIPAddr, HTARGET &hTarget) 625 | { 626 | TMAPI_TCPIP_CONNECT_PROP oConnection; 627 | std::vector::iterator iter = Targets.begin(); 628 | 629 | while (iter != Targets.end()) 630 | { 631 | if (SN_SUCCEEDED( SNPS3GetConnectionInfo((*iter)->hTarget, &oConnection) )) 632 | { 633 | if (wcscmp(UTF8ToWChar(std::string(pszIPAddr)).c_str(), CUTF8ToWChar(oConnection.szIPAddress)) == 0) 634 | { 635 | hTarget = (*iter)->hTarget; 636 | return true; 637 | } 638 | } 639 | 640 | ++iter; 641 | } 642 | 643 | // If we didn't find a match there, do a DNS lookup 644 | std::string ipAddress; 645 | std::string dnsName; 646 | if (!GetHostnames(pszIPAddr, ipAddress, dnsName)) 647 | return false; 648 | 649 | // Now iterate again 650 | iter = Targets.begin(); 651 | 652 | while (iter != Targets.end()) 653 | { 654 | if (SN_SUCCEEDED( SNPS3GetConnectionInfo((*iter)->hTarget, &oConnection) )) 655 | { 656 | if (wcscmp(UTF8ToWChar(ipAddress).c_str(), CUTF8ToWChar(oConnection.szIPAddress)) == 0 657 | || wcscmp(UTF8ToWChar(dnsName).c_str(), CUTF8ToWChar(oConnection.szIPAddress)) == 0) 658 | { 659 | hTarget = (*iter)->hTarget; 660 | return true; 661 | } 662 | } 663 | 664 | ++iter; 665 | } 666 | 667 | return false; 668 | } 669 | 670 | bool SetUpTarget(void) 671 | { 672 | SNRESULT snr; 673 | 674 | // Enumerate available targets. 675 | if (SN_FAILED( snr = SNPS3EnumerateTargets(EnumCallBack) )) 676 | { 677 | debug_printf("Failed to enumerate targets\n"); 678 | return false; 679 | } 680 | 681 | // Attempt to get the target name from an environment variable... 682 | 683 | if (LaunchTargetPicker) 684 | { 685 | debug_printf("Launching target picker...\n"); 686 | if (SN_FAILED(snr = SNPS3PickTarget(NULL, &TargetID))) 687 | { 688 | debug_printf("Failed to pick target\n"); 689 | return false; 690 | } 691 | 692 | SNPS3TargetInfo targetInfo = {}; 693 | targetInfo.hTarget = TargetID; 694 | targetInfo.nFlags = SN_TI_TARGETID; 695 | 696 | if (SN_FAILED( snr = SNPS3GetTargetInfo(&targetInfo) )) 697 | { 698 | debug_printf("Failed to get target info\n"); 699 | return false; 700 | } 701 | 702 | TargetName = std::string(targetInfo.pszName); 703 | } 704 | 705 | if (TargetName.empty()) 706 | { 707 | wchar_t* pEnv = _wgetenv(L"PS3TARGET"); 708 | if (pEnv) 709 | TargetName = WCharToUTF8(pEnv); 710 | } 711 | 712 | if (Targets.size() == 1 && TargetName.empty()) 713 | { 714 | TargetName = Targets[0]->pszName; 715 | } 716 | 717 | // If no target has been selected then use the default target 718 | if (TargetName.empty()) 719 | { 720 | if (SN_S_OK == SNPS3GetDefaultTarget(&TargetID)) 721 | { 722 | SNPS3TargetInfo targetInfo = {}; 723 | targetInfo.hTarget = TargetID; 724 | targetInfo.nFlags = SN_TI_TARGETID; 725 | 726 | if (SN_FAILED( snr = SNPS3GetTargetInfo(&targetInfo) )) 727 | { 728 | debug_printf("Failed to get target info\n"); 729 | return false; 730 | } 731 | 732 | TargetName = std::string(targetInfo.pszName); 733 | } 734 | } 735 | 736 | // If no target has been selected then use the first one connected or the first one available. 737 | if (TargetName.empty()) 738 | { 739 | if (!FindFirstConnectedTarget()) 740 | { 741 | FindFirstAvailableTarget(); 742 | } 743 | } 744 | // Retrieve the target ID from the name or failing that IP. 745 | if (SN_FAILED(snr = SNPS3GetTargetFromName(TargetName.c_str(), &TargetID))) 746 | { 747 | if (!GetTargetFromAddress(TargetName.c_str(), TargetID)) 748 | { 749 | debug_printf("Failed to find target! Please ensure target name/ip/hostname is correct\n"); 750 | return false; 751 | } 752 | } 753 | 754 | return true; 755 | } 756 | 757 | //-------------------------------------------------------------------------- 758 | void Kick() 759 | { 760 | SNRESULT snr = SN_S_OK; 761 | int Kicks = 0; 762 | 763 | do 764 | { 765 | snr = SNPS3Kick(); 766 | ++Kicks; 767 | 768 | } while (snr == SN_S_OK); 769 | } 770 | 771 | //-------------------------------------------------------------------------- 772 | // Process target specific events (see TargetEventCallback). 773 | static void ProcessTargetSpecificEvent(uint uDataLen, byte *pData) 774 | { 775 | SNPS3_DBG_EVENT_HDR *pDbgHeader = (SNPS3_DBG_EVENT_HDR *)pData; 776 | SNPS3_DBG_EVENT_DATA *pDbgData = (SNPS3_DBG_EVENT_DATA *)(pData + sizeof(SNPS3_DBG_EVENT_HDR)); 777 | debug_event_t ev; 778 | SNRESULT snr = SN_S_OK; 779 | 780 | switch (pDbgData->uEventType) 781 | { 782 | case SNPS3_DBG_EVENT_PROCESS_CREATE: 783 | { 784 | debug_printf("SNPS3_DBG_EVENT_PROCESS_CREATE\n"); 785 | } 786 | break; 787 | 788 | case SNPS3_DBG_EVENT_PROCESS_EXIT: 789 | { 790 | debug_printf("SNPS3_DBG_EVENT_PROCESS_EXIT\n"); 791 | 792 | ev.eid = PROCESS_EXIT; 793 | ev.pid = ProcessID; 794 | ev.tid = NO_THREAD; 795 | ev.ea = BADADDR; 796 | ev.handled = true; 797 | ev.exit_code = bswap64(pDbgData->ppu_process_exit.uExitCode); 798 | 799 | events.enqueue(ev, IN_BACK); 800 | 801 | } 802 | break; 803 | 804 | case SNPS3_DBG_EVENT_PPU_EXP_TRAP: 805 | { 806 | debug_printf("-> SNPS3_DBG_EVENT_PPU_EXP_TRAP <-\n"); 807 | 808 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_trap.uPPUThreadID), bswap64(pDbgData->ppu_exc_trap.uPC)); 809 | 810 | if (target_event.uEventType == SNPS3_DBG_EVENT_PPU_EXP_TRAP) 811 | break; 812 | 813 | if (singlestep == true || continue_from_bp == true) { 814 | 815 | uint32 addr; 816 | std::vector::iterator it; 817 | 818 | ev.eid = STEP; 819 | ev.pid = ProcessID; 820 | ev.tid = bswap64(pDbgData->ppu_exc_trap.uPPUThreadID); 821 | ev.ea = bswap64(pDbgData->ppu_exc_trap.uPC); 822 | ev.handled = true; 823 | ev.exc.code = 0; 824 | ev.exc.can_cont = true; 825 | ev.exc.ea = BADADDR; 826 | 827 | events.enqueue(ev, IN_BACK); 828 | 829 | while (!step_bpts.empty()) 830 | { 831 | addr = step_bpts.back(); 832 | step_bpts.pop_back(); 833 | 834 | it = std::find(main_bpts.begin(), main_bpts.end(), addr); 835 | if (it == main_bpts.end()) { 836 | 837 | main_bpts_map.erase(addr); 838 | 839 | if (SN_FAILED( snr = SNPS3ClearBreakPoint(TargetID, PS3_UI_CPU, ProcessID, bswap64(pDbgData->ppu_exc_trap.uPPUThreadID), addr))) 840 | { 841 | msg("SNPS3ClearBreakPoint Error: %d\n", snr); 842 | 843 | } else { 844 | 845 | debug_printf("step bpt cleared\n"); 846 | } 847 | } 848 | 849 | } 850 | 851 | if (continue_from_bp == true) 852 | { 853 | continue_from_bp = false; 854 | } else { 855 | singlestep = false; 856 | } 857 | 858 | } else { 859 | 860 | ev.eid = BREAKPOINT; 861 | ev.pid = ProcessID; 862 | ev.tid = bswap64(pDbgData->ppu_exc_trap.uPPUThreadID); 863 | ev.ea = bswap64(pDbgData->ppu_exc_trap.uPC); 864 | ev.handled = true; 865 | ev.bpt.hea = BADADDR; 866 | ev.bpt.kea = BADADDR; 867 | ev.exc.ea = BADADDR; 868 | 869 | events.enqueue(ev, IN_BACK); 870 | 871 | } 872 | } 873 | break; 874 | 875 | case SNPS3_DBG_EVENT_PPU_EXP_PREV_INT: 876 | { 877 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_PREV_INT\n"); 878 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_prev_int.uPPUThreadID), bswap64(pDbgData->ppu_exc_prev_int.uPC)); 879 | 880 | ev.eid = EXCEPTION; 881 | ev.pid = ProcessID; 882 | ev.tid = bswap64(pDbgData->ppu_exc_prev_int.uPPUThreadID); 883 | ev.ea = BADADDR; 884 | ev.handled = true; 885 | ev.exc.code = 0; 886 | ev.exc.can_cont = false; 887 | ev.exc.ea = bswap64(pDbgData->ppu_exc_prev_int.uPC); 888 | qstrncpy(ev.exc.info, "privilege instruction", sizeof(ev.exc.info)); 889 | 890 | events.enqueue(ev, IN_BACK); 891 | 892 | } 893 | break; 894 | 895 | case SNPS3_DBG_EVENT_PPU_EXP_ALIGNMENT: 896 | { 897 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_ALIGNMENT\n"); 898 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_alignment.uPPUThreadID), bswap64(pDbgData->ppu_exc_alignment.uPC)); 899 | 900 | ev.eid = EXCEPTION; 901 | ev.pid = ProcessID; 902 | ev.tid = bswap64(pDbgData->ppu_exc_alignment.uPPUThreadID); 903 | ev.ea = BADADDR; 904 | ev.handled = true; 905 | ev.exc.code = 0; 906 | ev.exc.can_cont = false; 907 | ev.exc.ea = bswap64(pDbgData->ppu_exc_alignment.uPC); 908 | qstrncpy(ev.exc.info, "alignment interrupt", sizeof(ev.exc.info)); 909 | 910 | events.enqueue(ev, IN_BACK); 911 | 912 | } 913 | break; 914 | 915 | case SNPS3_DBG_EVENT_PPU_EXP_ILL_INST: 916 | { 917 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_ILL_INST\n"); 918 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_ill_inst.uPPUThreadID), bswap64(pDbgData->ppu_exc_ill_inst.uPC)); 919 | debug_printf("DSISR = 0x%llX\n", bswap64(pDbgData->ppu_exc_ill_inst.uDSISR)); 920 | 921 | ev.eid = EXCEPTION; 922 | ev.pid = ProcessID; 923 | ev.tid = bswap64(pDbgData->ppu_exc_ill_inst.uPPUThreadID); 924 | ev.ea = BADADDR; 925 | ev.handled = true; 926 | ev.exc.code = 0; 927 | ev.exc.can_cont = false; 928 | ev.exc.ea = bswap64(pDbgData->ppu_exc_ill_inst.uPC); 929 | qstrncpy(ev.exc.info, "illegal instruction", sizeof(ev.exc.info)); 930 | 931 | events.enqueue(ev, IN_BACK); 932 | 933 | } 934 | break; 935 | 936 | case SNPS3_DBG_EVENT_PPU_EXP_TEXT_HTAB_MISS: 937 | { 938 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_TEXT_HTAB_MISS\n"); 939 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_text_htab_miss.uPPUThreadID), bswap64(pDbgData->ppu_exc_text_htab_miss.uPC)); 940 | 941 | ev.eid = EXCEPTION; 942 | ev.pid = ProcessID; 943 | ev.tid = bswap64(pDbgData->ppu_exc_text_htab_miss.uPPUThreadID); 944 | ev.ea = BADADDR; 945 | ev.handled = true; 946 | ev.exc.code = 0; 947 | ev.exc.can_cont = false; 948 | ev.exc.ea = bswap64(pDbgData->ppu_exc_text_htab_miss.uPC); 949 | qstrncpy(ev.exc.info, "instruction storage interrupt", sizeof(ev.exc.info)); 950 | 951 | events.enqueue(ev, IN_BACK); 952 | 953 | } 954 | break; 955 | 956 | case SNPS3_DBG_EVENT_PPU_EXP_TEXT_SLB_MISS: 957 | { 958 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_TEXT_SLB_MISS\n"); 959 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_text_slb_miss.uPPUThreadID), bswap64(pDbgData->ppu_exc_text_slb_miss.uPC)); 960 | 961 | ev.eid = EXCEPTION; 962 | ev.pid = ProcessID; 963 | ev.tid = bswap64(pDbgData->ppu_exc_text_slb_miss.uPPUThreadID); 964 | ev.ea = BADADDR; 965 | ev.handled = true; 966 | ev.exc.code = 0; 967 | ev.exc.can_cont = false; 968 | ev.exc.ea = bswap64(pDbgData->ppu_exc_text_slb_miss.uPC); 969 | qstrncpy(ev.exc.info, "instruction segment interrupt", sizeof(ev.exc.info)); 970 | 971 | events.enqueue(ev, IN_BACK); 972 | 973 | } 974 | break; 975 | 976 | case SNPS3_DBG_EVENT_PPU_EXP_DATA_HTAB_MISS: 977 | { 978 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_DATA_HTAB_MISS\n"); 979 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_data_htab_miss.uPPUThreadID), bswap64(pDbgData->ppu_exc_data_htab_miss.uPC)); 980 | 981 | ev.eid = EXCEPTION; 982 | ev.pid = ProcessID; 983 | ev.tid = bswap64(pDbgData->ppu_exc_data_htab_miss.uPPUThreadID); 984 | ev.ea = BADADDR; 985 | ev.handled = true; 986 | ev.exc.code = 0; 987 | ev.exc.can_cont = false; 988 | ev.exc.ea = bswap64(pDbgData->ppu_exc_data_htab_miss.uPC); 989 | qstrncpy(ev.exc.info, "data storage interrupt", sizeof(ev.exc.info)); 990 | 991 | events.enqueue(ev, IN_BACK); 992 | 993 | } 994 | break; 995 | 996 | case SNPS3_DBG_EVENT_PPU_EXP_FLOAT: 997 | { 998 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_FLOAT\n"); 999 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_float.uPPUThreadID), bswap64(pDbgData->ppu_exc_float.uPC)); 1000 | 1001 | ev.eid = EXCEPTION; 1002 | ev.pid = ProcessID; 1003 | ev.tid = bswap64(pDbgData->ppu_exc_float.uPPUThreadID); 1004 | ev.ea = BADADDR; 1005 | ev.handled = true; 1006 | ev.exc.code = 0; 1007 | ev.exc.can_cont = true; 1008 | ev.exc.ea = bswap64(pDbgData->ppu_exc_float.uPC); 1009 | qstrncpy(ev.exc.info, "floating point enabled exception", sizeof(ev.exc.info)); 1010 | 1011 | events.enqueue(ev, IN_BACK); 1012 | 1013 | } 1014 | break; 1015 | 1016 | case SNPS3_DBG_EVENT_PPU_EXP_DATA_SLB_MISS: 1017 | { 1018 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_DATA_SLB_MISS\n"); 1019 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_data_slb_miss.uPPUThreadID), bswap64(pDbgData->ppu_exc_data_slb_miss.uPC)); 1020 | 1021 | ev.eid = EXCEPTION; 1022 | ev.pid = ProcessID; 1023 | ev.tid = bswap64(pDbgData->ppu_exc_data_slb_miss.uPPUThreadID); 1024 | ev.ea = BADADDR; 1025 | ev.handled = true; 1026 | ev.exc.code = 0; 1027 | ev.exc.can_cont = false; 1028 | ev.exc.ea = bswap64(pDbgData->ppu_exc_data_slb_miss.uPC); 1029 | qstrncpy(ev.exc.info, "data segment interrupt", sizeof(ev.exc.info)); 1030 | 1031 | events.enqueue(ev, IN_BACK); 1032 | 1033 | } 1034 | break; 1035 | 1036 | case SNPS3_DBG_EVENT_PPU_EXP_DABR_MATCH: 1037 | { 1038 | debug_printf("-> SNPS3_DBG_EVENT_PPU_EXP_DABR_MATCH <-\n"); 1039 | 1040 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_dabr_match.uPPUThreadID), bswap64(pDbgData->ppu_exc_dabr_match.uPC)); 1041 | 1042 | if (target_event.uEventType == SNPS3_DBG_EVENT_PPU_EXP_DABR_MATCH) 1043 | break; 1044 | 1045 | ev.eid = BREAKPOINT; 1046 | ev.pid = ProcessID; 1047 | ev.tid = bswap64(pDbgData->ppu_exc_dabr_match.uPPUThreadID); 1048 | ev.ea = bswap64(pDbgData->ppu_exc_dabr_match.uPC); 1049 | ev.handled = true; 1050 | ev.bpt.hea = dabr_addr; 1051 | ev.bpt.kea = BADADDR; 1052 | ev.exc.ea = BADADDR; 1053 | 1054 | events.enqueue(ev, IN_BACK); 1055 | } 1056 | break; 1057 | 1058 | //! Notification that a PPU thread was stopped by DBGP_STOP_PPU_THREAD. 1059 | case SNPS3_DBG_EVENT_PPU_EXP_STOP: 1060 | { 1061 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_STOP\n"); 1062 | 1063 | debug_printf("ThreadID = 0x%llX, PC = 0x%llX\n", bswap64(pDbgData->ppu_exc_stop.uPPUThreadID), bswap64(pDbgData->ppu_exc_stop.uPC)); 1064 | 1065 | //suspend_thread(bswap64(pDbgData->ppu_exc_stop.uPPUThreadID)); 1066 | 1067 | } 1068 | break; 1069 | 1070 | //! Notification that a primary PPU thread was stopped at entry point after process was created. 1071 | case SNPS3_DBG_EVENT_PPU_EXP_STOP_INIT: 1072 | { 1073 | debug_printf("SNPS3_DBG_EVENT_PPU_EXP_STOP_INIT\n"); 1074 | //pDbgData->ppu_exc_stop_init; 1075 | } 1076 | break; 1077 | 1078 | //! Notification that a memory access trap interrupt occurred. 1079 | case SNPS3_DBG_EVENT_PPU_EXC_DATA_MAT: 1080 | { 1081 | debug_printf("SNPS3_DBG_EVENT_PPU_EXC_DATA_MAT\n"); 1082 | //pDbgData->ppu_exc_data_mat; 1083 | } 1084 | break; 1085 | 1086 | case SNPS3_DBG_EVENT_PPU_THREAD_CREATE: 1087 | { 1088 | debug_printf("SNPS3_DBG_EVENT_PPU_THREAD_CREATE\n"); 1089 | 1090 | debug_printf("ThreadID = 0x%llX\n", bswap64(pDbgData->ppu_thread_create.uPPUThreadID)); 1091 | 1092 | ev.eid = THREAD_START; 1093 | ev.pid = ProcessID; 1094 | ev.tid = bswap64(pDbgData->ppu_thread_create.uPPUThreadID); 1095 | ev.ea = BADADDR; 1096 | ev.handled = true; 1097 | 1098 | events.enqueue(ev, IN_BACK); 1099 | 1100 | } 1101 | break; 1102 | 1103 | case SNPS3_DBG_EVENT_PPU_THREAD_EXIT: 1104 | { 1105 | debug_printf("SNPS3_DBG_EVENT_PPU_THREAD_EXIT\n"); 1106 | 1107 | debug_printf("ThreadID = 0x%llX\n", bswap64(pDbgData->ppu_thread_exit.uPPUThreadID)); 1108 | 1109 | ev.eid = THREAD_EXIT; 1110 | ev.pid = ProcessID; 1111 | ev.tid = bswap64(pDbgData->ppu_thread_exit.uPPUThreadID); 1112 | ev.ea = BADADDR; 1113 | ev.handled = true; 1114 | ev.exit_code = 0; 1115 | 1116 | events.enqueue(ev, IN_BACK); 1117 | 1118 | } 1119 | break; 1120 | 1121 | case SNPS3_DBG_EVENT_PRX_LOAD: 1122 | { 1123 | debug_printf("SNPS3_DBG_EVENT_PRX_LOAD\n"); 1124 | 1125 | debug_printf("ThreadID = 0x%llX, ModuleID = 0x%X\n", bswap64(pDbgData->prx_load.uPPUThreadID), bswap32(pDbgData->prx_load.uPRXID)); 1126 | 1127 | uint64 ModuleInfoSize = 1024; 1128 | SNPS3MODULEINFO *ModuleInfo; 1129 | 1130 | ModuleInfo = (SNPS3MODULEINFO *)malloc(ModuleInfoSize); 1131 | 1132 | SNPS3GetModuleInfo(TargetID, ProcessID, bswap32(pDbgData->prx_load.uPRXID), &ModuleInfoSize, ModuleInfo); 1133 | 1134 | ev.eid = LIBRARY_LOAD; 1135 | ev.pid = ProcessID; 1136 | ev.tid = bswap64(pDbgData->prx_load.uPPUThreadID); 1137 | ev.ea = BADADDR; 1138 | ev.handled = true; 1139 | 1140 | _snprintf(ev.modinfo.name, MAXSTR, "%s - %s", ModuleInfo->Hdr.aElfName, ModuleInfo->Hdr.aName); 1141 | 1142 | ev.modinfo.base = ModuleInfo->Segments->uBase; 1143 | ev.modinfo.size = ModuleInfo->Segments->uMemSize; 1144 | ev.modinfo.rebase_to = BADADDR; 1145 | 1146 | events.enqueue(ev, IN_BACK); 1147 | 1148 | modules[bswap32(pDbgData->prx_load.uPRXID)] = ev.modinfo.name; 1149 | 1150 | free(ModuleInfo); 1151 | } 1152 | break; 1153 | 1154 | case SNPS3_DBG_EVENT_PRX_UNLOAD: 1155 | { 1156 | debug_printf("SNPS3_DBG_EVENT_PRX_UNLOAD\n"); 1157 | 1158 | debug_printf("ThreadID = 0x%llX, ModuleID = 0x%X\n", bswap64(pDbgData->prx_unload.uPPUThreadID), bswap32(pDbgData->prx_unload.uPRXID)); 1159 | 1160 | ev.eid = LIBRARY_UNLOAD; 1161 | ev.pid = ProcessID; 1162 | ev.tid = bswap64(pDbgData->prx_unload.uPPUThreadID); 1163 | ev.ea = BADADDR; 1164 | ev.handled = true; 1165 | 1166 | qstrncpy(ev.info, modules[bswap32(pDbgData->prx_unload.uPRXID)].c_str(), sizeof(ev.info)); 1167 | 1168 | events.enqueue(ev, IN_BACK); 1169 | 1170 | modules.erase(bswap32(pDbgData->prx_unload.uPRXID)); 1171 | } 1172 | break; 1173 | 1174 | } 1175 | } 1176 | 1177 | //-------------------------------------------------------------------------- 1178 | // Prints details of received target events. 1179 | static void ProcessTargetEvent(HTARGET hTarget, uint uDataLen, byte *pData) 1180 | { 1181 | uint uDataRemaining = uDataLen; 1182 | 1183 | while (uDataRemaining) 1184 | { 1185 | SN_EVENT_TARGET_HDR *pHeader = (SN_EVENT_TARGET_HDR *)pData; 1186 | 1187 | switch (pHeader->uEvent) 1188 | { 1189 | case SN_TGT_EVENT_TARGET_SPECIFIC: 1190 | { 1191 | ProcessTargetSpecificEvent(pHeader->uSize, pData + sizeof(SN_EVENT_TARGET_HDR)); 1192 | 1193 | memcpy(&target_event, pData + sizeof(SN_EVENT_TARGET_HDR) + sizeof(SNPS3_DBG_EVENT_HDR), 0x20); 1194 | 1195 | break; 1196 | } 1197 | } 1198 | 1199 | uDataRemaining -= pHeader->uSize; 1200 | pData += pHeader->uSize; 1201 | } 1202 | } 1203 | 1204 | //-------------------------------------------------------------------------- 1205 | // Process target event notifications. 1206 | static void __stdcall TargetEventCallback(HTARGET hTarget, uint uEventType, uint /*uEvent*/, 1207 | SNRESULT snr, uint uDataLen, byte *pData, void* /*pUser*/) 1208 | { 1209 | if (SN_FAILED( snr )) 1210 | return; 1211 | 1212 | switch (uEventType) 1213 | { 1214 | case SN_EVENT_TARGET: 1215 | ProcessTargetEvent(hTarget, uDataLen, pData); 1216 | break; 1217 | } 1218 | } 1219 | 1220 | //-------------------------------------------------------------------------- 1221 | // Initialize debugger 1222 | static bool idaapi init_debugger(const char *hostname, int port_num, const char *password) 1223 | { 1224 | SNRESULT snr = SN_S_OK; 1225 | 1226 | if (SN_FAILED( snr = SNPS3InitTargetComms() )) 1227 | { 1228 | msg("Failed to initialize PS3TM SDK\n"); 1229 | return false; 1230 | } 1231 | 1232 | if (!SetUpTarget() || !ConnectToActiveTarget()) 1233 | { 1234 | msg("Error connecting to target %s!\n", UTF8ToWChar(TargetName).c_str()); 1235 | return false; 1236 | } 1237 | 1238 | SNPS3RegisterTargetEventHandler(TargetID, TargetEventCallback, NULL); 1239 | 1240 | set_idc_func_ex("threadlst", idc_threadlst, idc_threadlst_args, 0); 1241 | 1242 | return true; 1243 | } 1244 | 1245 | //-------------------------------------------------------------------------- 1246 | // Terminate debugger 1247 | static bool idaapi term_debugger(void) 1248 | { 1249 | // Do post stuff like disconnecting from target 1250 | if (AlwaysDC || (!WasOriginallyConnected)) 1251 | { 1252 | if (TargetID != 0xffffffff) 1253 | { 1254 | SNPS3Disconnect(TargetID); 1255 | debug_printf("Disconnect\n"); 1256 | } 1257 | } 1258 | 1259 | SNPS3CloseTargetComms(); 1260 | //SNPS3Exit(); 1261 | 1262 | set_idc_func_ex("threadlst", NULL, idc_threadlst_args, 0); 1263 | 1264 | return true; 1265 | } 1266 | 1267 | //-------------------------------------------------------------------------- 1268 | int idaapi process_get_info(int n, process_info_t *info) 1269 | { 1270 | uint32 NumProcesses; 1271 | uint32* ProcessesList; 1272 | SNPS3PROCESSINFO* ProcessesInfo; 1273 | uint32 ProcessesInfoSize; 1274 | SNRESULT snr = SN_S_OK; 1275 | char* p; 1276 | 1277 | if (SN_FAILED( snr = SNPS3ProcessList(TargetID, &NumProcesses, NULL))) 1278 | { 1279 | debug_printf("SNPS3ProcessList Error: %d\n", snr); 1280 | return 0; 1281 | } 1282 | 1283 | if (n > int(NumProcesses - 1)) 1284 | return 0; 1285 | 1286 | ProcessesList = (uint32 *)malloc(NumProcesses * sizeof(uint32)); 1287 | 1288 | if (SN_FAILED( snr = SNPS3ProcessList(TargetID, &NumProcesses, ProcessesList))) 1289 | { 1290 | debug_printf("SNPS3ProcessList Error: %d\n", snr); 1291 | return 0; 1292 | } 1293 | 1294 | snr = SNPS3ProcessInfo(TargetID, ProcessesList[n], &ProcessesInfoSize, NULL); 1295 | 1296 | ProcessesInfo = (SNPS3PROCESSINFO *)malloc(ProcessesInfoSize); 1297 | 1298 | if (SN_FAILED( snr = SNPS3ProcessInfo(TargetID, ProcessesList[n], &ProcessesInfoSize, ProcessesInfo))) 1299 | { 1300 | debug_printf("SNPS3ProcessInfo Error: %d\n", snr); 1301 | return 0; 1302 | } 1303 | 1304 | info->pid = ProcessesList[n]; 1305 | qstrncpy(info->name, ProcessesInfo->Hdr.szPath, sizeof(info->name)); 1306 | 1307 | p = strrchr(ProcessesInfo->Hdr.szPath, '/'); 1308 | process_names[ProcessesList[n]] = p + 1; 1309 | 1310 | free(ProcessesInfo); 1311 | 1312 | free(ProcessesList); 1313 | 1314 | return 1; 1315 | } 1316 | 1317 | static const char *get_state_name(uint32 State) 1318 | { 1319 | switch ( State ) 1320 | { 1321 | case SNPS3_PPU_IDLE: return "IDLE"; 1322 | case SNPS3_PPU_RUNNABLE: return "RUNNABLE"; 1323 | case SNPS3_PPU_ONPROC: return "ONPROC"; 1324 | case SNPS3_PPU_SLEEP: return "SLEEP"; 1325 | case SNPS3_PPU_SUSPENDED: return "SUSPENDED"; 1326 | case SNPS3_PPU_SLEEP_SUSPENDED: return "SLEEP_SUSPENDED"; 1327 | case SNPS3_PPU_STOP: return "STOP"; 1328 | case SNPS3_PPU_ZOMBIE: return "ZOMBIE"; 1329 | case SNPS3_PPU_DELETED: return "DELETED"; 1330 | default: return "???"; 1331 | } 1332 | } 1333 | 1334 | static error_t idaapi idc_threadlst(idc_value_t *argv, idc_value_t *res) 1335 | { 1336 | get_threads_info(); 1337 | return eOk; 1338 | } 1339 | 1340 | void get_threads_info(void) 1341 | { 1342 | uint32 NumPPUThreads; 1343 | uint32 NumSPUThreadGroups; 1344 | uint64 *PPUThreadIDs; 1345 | uint64 *SPUThreadGroupIDs; 1346 | uint32 ThreadInfoSize = 1024; 1347 | SNPS3_PPU_THREAD_INFO *ThreadInfo; 1348 | SNRESULT snr = SN_S_OK; 1349 | debug_event_t ev; 1350 | 1351 | SNPS3ThreadList(TargetID, ProcessID, &NumPPUThreads, NULL, &NumSPUThreadGroups, NULL); 1352 | 1353 | PPUThreadIDs = (uint64 *)malloc(NumPPUThreads * sizeof(uint64)); 1354 | SPUThreadGroupIDs = (uint64 *)malloc(NumSPUThreadGroups * sizeof(uint64)); 1355 | 1356 | SNPS3ThreadList(TargetID, ProcessID, &NumPPUThreads, PPUThreadIDs, &NumSPUThreadGroups, SPUThreadGroupIDs); 1357 | 1358 | ThreadInfo = (SNPS3_PPU_THREAD_INFO *)malloc(ThreadInfoSize); 1359 | 1360 | //debug_printf(" === PPU THREAD INFO === \n"); 1361 | 1362 | for(uint32 i=0;iuThreadID, get_state_name(ThreadInfo->uState), (const char*)(ThreadInfo + 1)); 1373 | 1374 | if (attaching == true) 1375 | { 1376 | ev.eid = THREAD_START; 1377 | ev.pid = ProcessID; 1378 | ev.tid = ThreadInfo->uThreadID; 1379 | ev.ea = read_pc_register((uint32)ThreadInfo->uThreadID); 1380 | ev.handled = true; 1381 | 1382 | events.enqueue(ev, IN_BACK); 1383 | 1384 | clear_all_bp(ThreadInfo->uThreadID); 1385 | 1386 | if (ThreadInfo->uState == SNPS3_PPU_STOP) 1387 | { 1388 | //suspend_thread(ThreadInfo->uThreadID); 1389 | } 1390 | } 1391 | } 1392 | } 1393 | 1394 | //debug_printf(" === END === \n"); 1395 | 1396 | free(ThreadInfo); 1397 | 1398 | free(PPUThreadIDs); 1399 | free(SPUThreadGroupIDs); 1400 | } 1401 | 1402 | int get_thread_state(uint32 tid) 1403 | { 1404 | SNRESULT snr = SN_S_OK; 1405 | uint32 ThreadInfoSize = 1024; 1406 | SNPS3_PPU_THREAD_INFO *ThreadInfo; 1407 | int state; 1408 | 1409 | ThreadInfo = (SNPS3_PPU_THREAD_INFO *)malloc(ThreadInfoSize); 1410 | 1411 | if (SN_FAILED( snr = SNPS3ThreadInfo(TargetID, PS3_UI_CPU, ProcessID, tid, &ThreadInfoSize, (byte *)ThreadInfo))) 1412 | { 1413 | msg("SNPS3ThreadInfo Error: %d\n", snr); 1414 | state = -1; 1415 | 1416 | } else { 1417 | 1418 | msg("ThreadID: 0x%llX, State: %s, Name: %s\n", ThreadInfo->uThreadID, get_state_name(ThreadInfo->uState), (const char*)(ThreadInfo + 1)); 1419 | state = ThreadInfo->uState; 1420 | } 1421 | 1422 | free(ThreadInfo); 1423 | 1424 | return state; 1425 | } 1426 | 1427 | void get_modules_info(void) 1428 | { 1429 | uint32 NumModules; 1430 | uint32 *ModuleIDs; 1431 | uint64 ModuleInfoSize = 1024; 1432 | SNPS3MODULEINFO *ModuleInfo; 1433 | SNRESULT snr = SN_S_OK; 1434 | debug_event_t ev; 1435 | 1436 | SNPS3GetModuleList(TargetID, ProcessID, &NumModules, NULL); 1437 | 1438 | ModuleIDs = (uint32 *)malloc(NumModules * sizeof(uint32)); 1439 | 1440 | SNPS3GetModuleList(TargetID, ProcessID, &NumModules, ModuleIDs); 1441 | 1442 | ModuleInfo = (SNPS3MODULEINFO *)malloc(ModuleInfoSize); 1443 | 1444 | //debug_printf(" === MODULE INFO === \n"); 1445 | 1446 | for(uint32 i=0;iHdr.aElfName, ModuleInfo->Hdr.aName, *(uint16 *)ModuleInfo->Hdr.aVersion, ModuleInfo->Hdr.uAttribute, ModuleInfo->Hdr.uStartEntry, ModuleInfo->Hdr.uStopEntry, ModuleInfo->Hdr.uNumSegments); 1457 | 1458 | if (attaching == true) 1459 | { 1460 | ev.eid = LIBRARY_LOAD; 1461 | ev.pid = ProcessID; 1462 | ev.tid = NO_THREAD; 1463 | ev.ea = BADADDR; 1464 | ev.handled = true; 1465 | 1466 | _snprintf(ev.modinfo.name, MAXSTR, "%s - %s", ModuleInfo->Hdr.aElfName, ModuleInfo->Hdr.aName); 1467 | 1468 | ev.modinfo.base = ModuleInfo->Segments->uBase; 1469 | ev.modinfo.size = ModuleInfo->Segments->uMemSize; 1470 | ev.modinfo.rebase_to = BADADDR; 1471 | 1472 | events.enqueue(ev, IN_BACK); 1473 | 1474 | modules[ModuleIDs[i]] = ev.modinfo.name; 1475 | } 1476 | 1477 | for(uint32 j=0;jHdr.uNumSegments;j++) { 1478 | 1479 | //debug_printf("\t %lld: Base: 0x%llX, FileSize: 0x%llX, MemSize: 0x%llX, ElfType: 0x%llX\n", ModuleInfo->Segments[j].uIndex, ModuleInfo->Segments[j].uBase, ModuleInfo->Segments[j].uFileSize, ModuleInfo->Segments[j].uMemSize, ModuleInfo->Segments[j].uElfType); 1480 | 1481 | } 1482 | } 1483 | } 1484 | 1485 | //debug_printf(" === END === \n"); 1486 | 1487 | free(ModuleInfo); 1488 | 1489 | free(ModuleIDs); 1490 | } 1491 | 1492 | void clear_all_bp(uint32 tid) 1493 | { 1494 | uint32 BPCount; 1495 | uint64 *BPAddress; 1496 | 1497 | SNPS3GetBreakPoints(TargetID, PS3_UI_CPU, ProcessID, tid, &BPCount, NULL); 1498 | 1499 | if (BPCount != 0) 1500 | { 1501 | BPAddress = (uint64 *)malloc(BPCount * sizeof(uint64)); 1502 | 1503 | SNPS3GetBreakPoints(TargetID, PS3_UI_CPU, ProcessID, tid, &BPCount, BPAddress); 1504 | 1505 | for(uint32 i=0;ieid == BREAKPOINT && event->bpt.hea != BADADDR) 1755 | { 1756 | debug_printf("get_debug_event: BREAKPOINT (HW)\n"); 1757 | 1758 | } else { 1759 | 1760 | debug_printf("get_debug_event: %s\n", get_event_name(event->eid)); 1761 | } 1762 | 1763 | #endif 1764 | 1765 | if (event->eid == PROCESS_ATTACH) 1766 | { 1767 | attaching = false; 1768 | } 1769 | 1770 | if (attaching == false) 1771 | { 1772 | memset(&target_event, 0, 0x20); 1773 | 1774 | Kick(); 1775 | } 1776 | 1777 | return GDE_ONE_EVENT; 1778 | } 1779 | 1780 | if (events.empty()) 1781 | break; 1782 | 1783 | }; 1784 | 1785 | if (attaching == false) 1786 | { 1787 | memset(&target_event, 0, 0x20); 1788 | 1789 | Kick(); 1790 | } 1791 | 1792 | return GDE_NO_EVENT; 1793 | } 1794 | 1795 | //-------------------------------------------------------------------------- 1796 | // Continue after handling the event 1797 | int idaapi continue_after_event(const debug_event_t *event) 1798 | { 1799 | if ( event == NULL ) 1800 | return false; 1801 | 1802 | #ifdef _DEBUG 1803 | 1804 | if (event->eid == BREAKPOINT && event->bpt.hea != BADADDR) 1805 | { 1806 | debug_printf("continue_after_event: BREAKPOINT (HW)\n"); 1807 | 1808 | } else { 1809 | 1810 | debug_printf("continue_after_event: %s\n", get_event_name(event->eid)); 1811 | } 1812 | 1813 | #endif 1814 | 1815 | if (event->eid == PROCESS_ATTACH || event->eid == PROCESS_SUSPEND || event->eid == STEP || event->eid == BREAKPOINT) { 1816 | 1817 | if (event->eid == BREAKPOINT) 1818 | { 1819 | if (addr_has_bp(event->ea) == true) 1820 | { 1821 | SNPS3ClearBreakPoint(TargetID, PS3_UI_CPU, ProcessID, -1, event->ea); 1822 | 1823 | do_step(event->tid, 0); 1824 | 1825 | SNPS3ProcessContinue(TargetID, ProcessID); 1826 | 1827 | memset(&target_event, 0, 0x20); 1828 | 1829 | continue_from_bp = true; 1830 | 1831 | Kick(); 1832 | 1833 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, -1, event->ea); 1834 | } 1835 | 1836 | if (event->bpt.hea == dabr_addr) 1837 | { 1838 | SNPS3SetDABR(TargetID, ProcessID, dabr_addr | 4); 1839 | 1840 | do_step(event->tid, 0); 1841 | 1842 | SNPS3ProcessContinue(TargetID, ProcessID); 1843 | 1844 | memset(&target_event, 0, 0x20); 1845 | 1846 | continue_from_bp = true; 1847 | 1848 | Kick(); 1849 | 1850 | SNPS3SetDABR(TargetID, ProcessID, dabr_addr | dabr_type); 1851 | 1852 | } 1853 | } 1854 | 1855 | SNPS3ProcessContinue(TargetID, ProcessID); 1856 | 1857 | memset(&target_event, 0, 0x20); 1858 | 1859 | //get_threads_info(); 1860 | 1861 | Kick(); 1862 | 1863 | } 1864 | 1865 | return true; 1866 | } 1867 | 1868 | //-------------------------------------------------------------------------- 1869 | void idaapi stopped_at_debug_event(bool dlls_added) 1870 | { 1871 | } 1872 | 1873 | //-------------------------------------------------------------------------- 1874 | int idaapi thread_suspend(thid_t tid) 1875 | { 1876 | debug_printf("thread_suspend: tid = 0x%X\n", tid); 1877 | 1878 | SNPS3ThreadStop(TargetID, PS3_UI_CPU, ProcessID, tid); 1879 | 1880 | get_thread_state(tid); 1881 | 1882 | return 1; 1883 | } 1884 | 1885 | //-------------------------------------------------------------------------- 1886 | int idaapi thread_continue(thid_t tid) 1887 | { 1888 | debug_printf("thread_continue: tid = 0x%X\n", tid); 1889 | 1890 | SNPS3ThreadContinue(TargetID, PS3_UI_CPU, ProcessID, tid); 1891 | 1892 | get_thread_state(tid); 1893 | 1894 | return 1; 1895 | } 1896 | 1897 | //------------------------------------------------------------------------- 1898 | int do_step(uint32 tid, uint32 dbg_notification) 1899 | { 1900 | uint32 ea; 1901 | uint32 instruction; 1902 | uint32 next_addr; 1903 | uint32 resolved_addr; 1904 | uint32 addr; 1905 | uint32 v; 1906 | int state; 1907 | 1908 | ea = read_pc_register(tid); 1909 | 1910 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, ea, 4, (byte *)&instruction); 1911 | if (instruction == *(uint32*)bpt_code) 1912 | instruction = main_bpts_map[ea]; 1913 | 1914 | instruction = bswap32(instruction); 1915 | 1916 | state = get_thread_state(tid); 1917 | 1918 | if (state == SNPS3_PPU_SLEEP) 1919 | { 1920 | msg("THIS THREAD SLEEPS!\n"); 1921 | } 1922 | 1923 | next_addr = ea + 4; 1924 | resolved_addr = next_addr; 1925 | 1926 | //case 1 - bge, bne, beq, blt... 1927 | if ( instruction >> 26 == 16 ) 1928 | { 1929 | addr = instruction & 0xFFFC; 1930 | 1931 | if ( addr & 0x8000 ) 1932 | addr = addr | 0xFFFF0000; 1933 | 1934 | if ( !(instruction & 2) ) 1935 | addr += ea; 1936 | 1937 | resolved_addr = addr; 1938 | 1939 | if ( instruction & 1 ) 1940 | { 1941 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, next_addr, 4, (byte *)&instruction); 1942 | if (instruction != *(uint32*)bpt_code) 1943 | main_bpts_map[next_addr] = instruction; 1944 | 1945 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, next_addr); 1946 | step_bpts.push_back(next_addr); 1947 | 1948 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 1949 | if (instruction != *(uint32*)bpt_code) 1950 | main_bpts_map[resolved_addr] = instruction; 1951 | 1952 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 1953 | step_bpts.push_back(resolved_addr); 1954 | 1955 | return 1; 1956 | } 1957 | 1958 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, next_addr, 4, (byte *)&instruction); 1959 | if (instruction != *(uint32*)bpt_code) 1960 | main_bpts_map[next_addr] = instruction; 1961 | 1962 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, next_addr); 1963 | step_bpts.push_back(next_addr); 1964 | 1965 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 1966 | if (instruction != *(uint32*)bpt_code) 1967 | main_bpts_map[resolved_addr] = instruction; 1968 | 1969 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 1970 | step_bpts.push_back(resolved_addr); 1971 | 1972 | return 1; 1973 | } 1974 | 1975 | //case 2 - bl, b 1976 | if ( instruction >> 26 == 18 ) 1977 | { 1978 | addr = instruction & 0x3FFFFFC; 1979 | 1980 | if ( addr & 0x2000000 ) 1981 | addr = addr | 0xFC000000; 1982 | 1983 | if ( !(instruction & 2) ) 1984 | addr += ea; 1985 | 1986 | resolved_addr = addr; 1987 | 1988 | if ( instruction & 1 ) 1989 | { 1990 | // bl 1991 | 1992 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 1993 | if (instruction != *(uint32*)bpt_code) 1994 | main_bpts_map[resolved_addr] = instruction; 1995 | 1996 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 1997 | step_bpts.push_back(resolved_addr); 1998 | 1999 | return 1; 2000 | } 2001 | 2002 | // b 2003 | 2004 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 2005 | if (instruction != *(uint32*)bpt_code) 2006 | main_bpts_map[resolved_addr] = instruction; 2007 | 2008 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 2009 | step_bpts.push_back(resolved_addr); 2010 | 2011 | return 1; 2012 | } 2013 | 2014 | //case 3 - all 2015 | if ( instruction >> 26 != 19 || instruction & 0xE000 ) 2016 | { 2017 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, next_addr, 4, (byte *)&instruction); 2018 | if (instruction != *(uint32*)bpt_code) 2019 | main_bpts_map[next_addr] = instruction; 2020 | 2021 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, next_addr); 2022 | step_bpts.push_back(next_addr); 2023 | 2024 | return 1; 2025 | } 2026 | 2027 | v = (instruction >> 1) & 0x3FF; 2028 | 2029 | //case 4 - blr, beqlr, blelr... 2030 | if ( v == 16 ) 2031 | { 2032 | resolved_addr = read_lr_register(tid); 2033 | 2034 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, next_addr, 4, (byte *)&instruction); 2035 | if (instruction != *(uint32*)bpt_code) 2036 | main_bpts_map[next_addr] = instruction; 2037 | 2038 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, next_addr); 2039 | step_bpts.push_back(next_addr); 2040 | 2041 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 2042 | if (instruction != *(uint32*)bpt_code) 2043 | main_bpts_map[resolved_addr] = instruction; 2044 | 2045 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 2046 | step_bpts.push_back(resolved_addr); 2047 | 2048 | return 1; 2049 | } 2050 | 2051 | //case 5 - bctrl, bctr, bltctr, bgtctrl... 2052 | if ( v != 528 ) 2053 | return 1; 2054 | 2055 | resolved_addr = read_ctr_register(tid); 2056 | 2057 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, next_addr, 4, (byte *)&instruction); 2058 | if (instruction != *(uint32*)bpt_code) 2059 | main_bpts_map[next_addr] = instruction; 2060 | 2061 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, next_addr); 2062 | step_bpts.push_back(next_addr); 2063 | 2064 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, resolved_addr, 4, (byte *)&instruction); 2065 | if (instruction != *(uint32*)bpt_code) 2066 | main_bpts_map[resolved_addr] = instruction; 2067 | 2068 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, tid, resolved_addr); 2069 | step_bpts.push_back(resolved_addr); 2070 | 2071 | return 1; 2072 | } 2073 | 2074 | //-------------------------------------------------------------------------- 2075 | // Run one instruction in the thread 2076 | int idaapi thread_set_step(thid_t tid) 2077 | { 2078 | int dbg_notification; 2079 | int result = 0; 2080 | 2081 | dbg_notification = get_running_notification(); 2082 | 2083 | if (dbg_notification == STEP_INTO || dbg_notification == STEP_OVER) { 2084 | result = do_step(tid, dbg_notification); 2085 | singlestep = true; 2086 | } 2087 | 2088 | return result; 2089 | } 2090 | 2091 | //------------------------------------------------------------------------- 2092 | uint32 read_pc_register(uint32 tid) 2093 | { 2094 | SNRESULT snr = SN_S_OK; 2095 | uint32 reg = SNPS3_pc; 2096 | byte result[SNPS3_REGLEN]; 2097 | 2098 | if (SN_FAILED( snr = SNPS3ThreadGetRegisters(TargetID, PS3_UI_CPU, ProcessID, tid, 1, ®, result))) 2099 | { 2100 | msg("read_pc_register -> SNPS3ThreadGetRegisters Error: %d\n", snr); 2101 | return BADADDR; 2102 | } 2103 | 2104 | return bswap32(*(uint32 *)(result + 4)); 2105 | } 2106 | 2107 | uint32 read_lr_register(uint32 tid) 2108 | { 2109 | SNRESULT snr = SN_S_OK; 2110 | uint32 reg = SNPS3_lr; 2111 | byte result[SNPS3_REGLEN]; 2112 | 2113 | if (SN_FAILED( snr = SNPS3ThreadGetRegisters(TargetID, PS3_UI_CPU, ProcessID, tid, 1, ®, result))) 2114 | { 2115 | msg("read_lr_register -> SNPS3ThreadGetRegisters Error: %d\n", snr); 2116 | return BADADDR; 2117 | } 2118 | 2119 | return bswap32(*(uint32 *)(result + 4)); 2120 | } 2121 | 2122 | uint32 read_ctr_register(uint32 tid) 2123 | { 2124 | SNRESULT snr = SN_S_OK; 2125 | uint32 reg = SNPS3_ctr; 2126 | byte result[SNPS3_REGLEN]; 2127 | 2128 | if (SN_FAILED( snr = SNPS3ThreadGetRegisters(TargetID, PS3_UI_CPU, ProcessID, tid, 1, ®, result))) 2129 | { 2130 | msg("read_ctr_register -> SNPS3ThreadGetRegisters Error: %d\n", snr); 2131 | return BADADDR; 2132 | } 2133 | 2134 | return bswap32(*(uint32 *)(result + 4)); 2135 | } 2136 | 2137 | //-------------------------------------------------------------------------- 2138 | // Read thread registers 2139 | int idaapi read_registers(thid_t tid, int clsmask, regval_t *values) 2140 | { 2141 | SNRESULT snr = SN_S_OK; 2142 | regval *RegsBuf; 2143 | 2144 | if ( values == NULL ) 2145 | { 2146 | debug_printf("NULL ptr detected !\n"); 2147 | return false; 2148 | } 2149 | 2150 | RegsBuf = (regval *)malloc(qnumber(registers_id) * SNPS3_REGLEN); 2151 | 2152 | if (SN_FAILED( snr = SNPS3ThreadGetRegisters(TargetID, PS3_UI_CPU, ProcessID, tid, qnumber(registers_id), registers_id, (byte *)RegsBuf))) 2153 | { 2154 | debug_printf("read_registers -> SNPS3ThreadGetRegisters Error: %d\n", snr); 2155 | return 1; 2156 | 2157 | } else { 2158 | 2159 | for(int i=0;i> 32); 2168 | } 2169 | 2170 | } else { 2171 | //for ( int i=R_XMM0; i < R_MXCSR; i++,xptr+=16 ) 2172 | // values[i].set_bytes(xptr, 16); 2173 | } 2174 | } 2175 | } 2176 | 2177 | return 1; 2178 | } 2179 | 2180 | //-------------------------------------------------------------------------- 2181 | // Write one thread register 2182 | int idaapi write_register(thid_t tid, int reg_idx, const regval_t *value) 2183 | { 2184 | SNRESULT snr = SN_S_OK; 2185 | uint32 reg; 2186 | uint64 val; 2187 | 2188 | if ( value == NULL ) 2189 | { 2190 | debug_printf("NULL ptr detected !\n"); 2191 | return false; 2192 | } 2193 | 2194 | //Ida Pro 6.1 has sign extension bug: if val is 32 bits, high 32 bits will be 0xFFFFFFFF 2195 | 2196 | if ( reg_idx > qnumber(registers) ) 2197 | { 2198 | debug_printf("wrong reg_idx !\n"); 2199 | return false; 2200 | } 2201 | 2202 | reg = registers_id[reg_idx]; 2203 | 2204 | val = bswap64(value->ival); 2205 | 2206 | if (SN_FAILED( snr = SNPS3ThreadSetRegisters(TargetID, PS3_UI_CPU, ProcessID, tid, 1, ®, (byte *)&val))) 2207 | { 2208 | msg("SNPS3ThreadSetRegisters Error: %d\n", snr); 2209 | return false; 2210 | } 2211 | 2212 | return 1; 2213 | } 2214 | 2215 | //-------------------------------------------------------------------------- 2216 | // Get information on the memory areas 2217 | // The debugger module fills 'areas'. The returned vector MUST be sorted. 2218 | // Returns: 2219 | // -3: use idb segmentation 2220 | // -2: no changes 2221 | // -1: the process does not exist anymore 2222 | // 0: failed 2223 | // 1: new memory layout is returned 2224 | int idaapi get_memory_info(meminfo_vec_t &areas) 2225 | { 2226 | /*SNRESULT snr = SN_S_OK; 2227 | uint32 AreaCount; 2228 | uint32 BufSize; 2229 | SNPS3VirtualMemoryArea* Buf; 2230 | 2231 | debug_printf("get_memory_info\n"); 2232 | 2233 | SNPS3GetVirtualMemoryInfo(TargetID, ProcessID, true, &AreaCount, &BufSize, NULL); 2234 | 2235 | debug_printf("BufSize: 0x%X\n", BufSize); 2236 | 2237 | Buf = (SNPS3VirtualMemoryArea *)malloc(BufSize); 2238 | 2239 | if (SN_FAILED( snr = SNPS3GetVirtualMemoryInfo(TargetID, ProcessID, true, &AreaCount, &BufSize, (byte *)Buf))) 2240 | { 2241 | msg("SNPS3GetVirtualMemoryInfo Error: %d\n", snr); 2242 | return -3; 2243 | } 2244 | 2245 | debug_printf("AreaCount: 0x%X\n", AreaCount); 2246 | 2247 | memory_info_t info; 2248 | 2249 | for(uint32 i = 0; i < AreaCount; i++) { 2250 | 2251 | debug_printf("Address: 0x%llX, Size: 0x%llX\n", Buf[i].uAddress, Buf[i].uVSize); 2252 | 2253 | info.startEA = Buf[i].uAddress; 2254 | info.endEA = Buf[i].uAddress + Buf[i].uVSize; 2255 | info.name = NULL; 2256 | info.sclass = NULL; 2257 | info.sbase = 0; 2258 | info.bitness = 1; 2259 | info.perm = 0; // SEGPERM_EXEC / SEGPERM_WRITE / SEGPERM_READ 2260 | 2261 | areas.push_back(info); 2262 | 2263 | } 2264 | 2265 | free(Buf);*/ 2266 | 2267 | memory_info_t info; 2268 | 2269 | info.startEA = 0; 2270 | info.endEA = 0xFFFF0000; 2271 | info.name = NULL; 2272 | info.sclass = NULL; 2273 | info.sbase = 0; 2274 | info.bitness = 1; 2275 | info.perm = 0; // SEGPERM_EXEC / SEGPERM_WRITE / SEGPERM_READ 2276 | 2277 | areas.push_back(info); 2278 | 2279 | return 1; 2280 | } 2281 | 2282 | //-------------------------------------------------------------------------- 2283 | // Read process memory 2284 | ssize_t idaapi read_memory(ea_t ea, void *buffer, size_t size) 2285 | { 2286 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, ea, size, (byte *)buffer); 2287 | 2288 | for(int i=0;i::iterator it; 2407 | uint32 orig_inst = -1; 2408 | uint32 BPCount; 2409 | int cnt = 0; 2410 | 2411 | //SNPS3GetBreakPoints(TargetID, PS3_UI_CPU, ProcessID, -1, &BPCount, NULL); 2412 | //debug_printf("BreakPoints sum: %d\n", BPCount); 2413 | 2414 | //bp_list(); 2415 | 2416 | for(i = 0; i < nadd; i++) { 2417 | 2418 | debug_printf("add_bpt: type: %d, ea: 0x%X, code: %d\n", bpts[i].type, bpts[i].ea, bpts[i].code); 2419 | 2420 | //BPT_SKIP 2421 | 2422 | switch(bpts[i].type) 2423 | { 2424 | case BPT_SOFT: 2425 | { 2426 | debug_printf("Software breakpoint\n"); 2427 | 2428 | SNPS3ProcessGetMemory(TargetID, PS3_UI_CPU, ProcessID, -1, bpts[i].ea, 4, (byte *)&orig_inst); 2429 | 2430 | if (orig_inst != *(uint32*)bpt_code) 2431 | main_bpts_map[bpts[i].ea] = orig_inst; 2432 | 2433 | //debug_printf("orig_inst = 0x%X\n", bswap32(orig_inst)); 2434 | 2435 | bpts[i].orgbytes.push_back(orig_inst); 2436 | 2437 | SNPS3SetBreakPoint(TargetID, PS3_UI_CPU, ProcessID, -1, bpts[i].ea); 2438 | 2439 | bpts[i].code = BPT_OK; 2440 | 2441 | main_bpts.push_back(bpts[i].ea); 2442 | 2443 | cnt++; 2444 | } 2445 | break; 2446 | 2447 | case BPT_EXEC: 2448 | { 2449 | debug_printf("Execute instruction\n"); 2450 | //bpts[i].size 2451 | 2452 | bpts[i].code = BPT_BAD_TYPE; 2453 | } 2454 | break; 2455 | 2456 | case BPT_WRITE: 2457 | { 2458 | debug_printf("Write access\n"); 2459 | //bpts[i].size 2460 | 2461 | if (dabr_is_set == false) 2462 | { 2463 | SNPS3ProcessStop(TargetID, ProcessID); 2464 | 2465 | SNPS3SetDABR(TargetID, ProcessID, bpts[i].ea | 6); 2466 | 2467 | debug_printf("DABR: 0x%X\n", bpts[i].ea | 6); 2468 | 2469 | SNPS3ProcessContinue(TargetID, ProcessID); 2470 | 2471 | dabr_addr = bpts[i].ea; 2472 | 2473 | dabr_type = 6; 2474 | 2475 | dabr_is_set = true; 2476 | 2477 | bpts[i].code = BPT_OK; 2478 | 2479 | cnt++; 2480 | 2481 | } else { 2482 | 2483 | msg("It's possible to set a single hardware breakpoint, DABR 0x%X is not set\n", bpts[i].ea); 2484 | bpts[i].code = BPT_TOO_MANY; 2485 | } 2486 | } 2487 | break; 2488 | 2489 | // No read access? 2490 | 2491 | case BPT_RDWR: 2492 | { 2493 | debug_printf("Read/write access\n"); 2494 | //bpts[i].size 2495 | 2496 | if (dabr_is_set == false) 2497 | { 2498 | SNPS3ProcessStop(TargetID, ProcessID); 2499 | 2500 | SNPS3SetDABR(TargetID, ProcessID, bpts[i].ea | 7); 2501 | 2502 | debug_printf("DABR: 0x%X\n", bpts[i].ea | 7); 2503 | 2504 | SNPS3ProcessContinue(TargetID, ProcessID); 2505 | 2506 | dabr_addr = bpts[i].ea; 2507 | 2508 | dabr_type = 7; 2509 | 2510 | dabr_is_set = true; 2511 | 2512 | bpts[i].code = BPT_OK; 2513 | 2514 | cnt++; 2515 | 2516 | } else { 2517 | 2518 | msg("It's possible to set a single hardware breakpoint, DABR 0x%X is not set\n", bpts[i].ea); 2519 | bpts[i].code = BPT_TOO_MANY; 2520 | } 2521 | } 2522 | break; 2523 | 2524 | default: 2525 | debug_printf("Unsupported BP type !\n"); 2526 | } 2527 | } 2528 | 2529 | for(i = 0; i < ndel; i++) { 2530 | 2531 | debug_printf("del_bpt: type: %d, ea: 0x%X, code: %d\n", bpts[nadd + i].type, bpts[nadd + i].ea, bpts[nadd + i].code); 2532 | 2533 | bpts[nadd + i].code = BPT_OK; 2534 | cnt++; 2535 | 2536 | switch(bpts[nadd + i].type) 2537 | { 2538 | case BPT_SOFT: 2539 | { 2540 | debug_printf("Software breakpoint\n"); 2541 | 2542 | bpts[nadd + i].orgbytes.pop_back(); 2543 | 2544 | SNPS3ClearBreakPoint(TargetID, PS3_UI_CPU, ProcessID, -1, bpts[nadd + i].ea); 2545 | 2546 | it = std::find(main_bpts.begin(), main_bpts.end(), bpts[nadd + i].ea); 2547 | 2548 | main_bpts.erase(it); 2549 | 2550 | main_bpts_map.erase(bpts[nadd + i].ea); 2551 | } 2552 | break; 2553 | 2554 | case BPT_WRITE: 2555 | case BPT_RDWR: 2556 | { 2557 | if (bpts[nadd + i].type == BPT_RDWR) 2558 | { 2559 | debug_printf("Read/write access\n"); 2560 | 2561 | } else { 2562 | 2563 | debug_printf("Write access\n"); 2564 | } 2565 | 2566 | dabr_is_set = false; 2567 | 2568 | dabr_addr = 0; 2569 | 2570 | SNPS3ProcessStop(TargetID, ProcessID); 2571 | 2572 | SNPS3SetDABR(TargetID, ProcessID, bpts[nadd + i].ea | 4); 2573 | 2574 | debug_printf("DABR: 0x%X\n", bpts[nadd + i].ea | 4); 2575 | 2576 | SNPS3ProcessContinue(TargetID, ProcessID); 2577 | } 2578 | break; 2579 | } 2580 | } 2581 | 2582 | //SNPS3GetBreakPoints(TargetID, PS3_UI_CPU, ProcessID, -1, &BPCount, NULL); 2583 | //debug_printf("BreakPoints sum: %d\n", BPCount); 2584 | 2585 | //bp_list(); 2586 | 2587 | return cnt; 2588 | } 2589 | 2590 | //-------------------------------------------------------------------------- 2591 | // Map process address 2592 | ea_t idaapi map_address(ea_t off, const regval_t *regs, int regnum) 2593 | { 2594 | if (regnum == 0) 2595 | { 2596 | } 2597 | 2598 | if (regs == NULL) // jump prediction 2599 | { 2600 | return BADADDR; 2601 | } 2602 | 2603 | if (regs[regnum].ival < 0x100000000 && regs[regnum].ival > 0x10200) 2604 | { 2605 | return regs[regnum].ival; 2606 | } 2607 | 2608 | return BADADDR; 2609 | } 2610 | 2611 | //------------------------------------------------------------------------- 2612 | int idaapi send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) 2613 | { 2614 | return 0; 2615 | } 2616 | 2617 | //-------------------------------------------------------------------------- 2618 | // 2619 | // DEBUGGER DESCRIPTION BLOCK 2620 | // 2621 | //-------------------------------------------------------------------------- 2622 | debugger_t debugger = 2623 | { 2624 | IDD_INTERFACE_VERSION, 2625 | DEBUGGER_NAME, // Short debugger name 2626 | DEBUGGER_ID_PLAYSTATION_3, // Debugger API module id 2627 | PROCESSOR_NAME, // Required processor name 2628 | DBG_FLAG_REMOTE | DBG_FLAG_NOHOST | DBG_FLAG_CAN_CONT_BPT, 2629 | 2630 | register_classes, // Array of register class names 2631 | RC_GENERAL, // Mask of default printed register classes 2632 | registers, // Array of registers 2633 | qnumber(registers), // Number of registers 2634 | 2635 | 0x1000, // Size of a memory page 2636 | 2637 | bpt_code, // Array of bytes for a breakpoint instruction 2638 | qnumber(bpt_code), // Size of this array 2639 | 0, // for miniidbs: use this value for the file type after attaching 2640 | 0, // reserved 2641 | 2642 | init_debugger, 2643 | term_debugger, 2644 | 2645 | process_get_info, 2646 | deci3_start_process, 2647 | deci3_attach_process, 2648 | deci3_detach_process, 2649 | rebase_if_required_to, 2650 | prepare_to_pause_process, 2651 | deci3_exit_process, 2652 | 2653 | get_debug_event, 2654 | continue_after_event, 2655 | NULL, //set_exception_info, 2656 | stopped_at_debug_event, 2657 | 2658 | thread_suspend, 2659 | thread_continue, 2660 | thread_set_step, 2661 | read_registers, 2662 | write_register, 2663 | NULL, //thread_get_sreg_base 2664 | 2665 | get_memory_info, 2666 | read_memory, 2667 | write_memory, 2668 | 2669 | is_ok_bpt, 2670 | update_bpts, 2671 | NULL, //update_lowcnds 2672 | NULL, //open_file 2673 | NULL, //close_file 2674 | NULL, //read_file 2675 | map_address, 2676 | NULL, //set_dbg_options 2677 | NULL, //get_debmod_extensions 2678 | NULL, //update_call_stack 2679 | NULL, //appcall 2680 | NULL, //cleanup_appcall 2681 | NULL, //eval_lowcnd 2682 | NULL, //write_file 2683 | send_ioctl, 2684 | }; 2685 | --------------------------------------------------------------------------------