gdbstub_plugin/src/debugger.h

275 lines
5.8 KiB
C
Raw Normal View History

2018-09-24 10:43:20 +02:00
#pragma once
#include "kernel.h"
#include "socket.h"
2022-02-08 14:48:41 +01:00
#include <coreinit/messagequeue.h>
#include <coreinit/mutex.h>
#include <coreinit/thread.h>
2018-09-24 10:43:20 +02:00
#include <cstdint>
#include <vector>
#define MESSAGE_COUNT 10
2022-02-08 14:44:53 +01:00
#define STACK_SIZE 0x8000
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
#define TRAP 0x7FE00008
2018-09-24 10:43:20 +02:00
2022-02-08 14:48:41 +01:00
extern OSThread **pThreadList;
#define ThreadList (*pThreadList)
2022-02-08 14:44:53 +01:00
template<int N>
2018-09-24 10:43:20 +02:00
class Bits {
public:
2022-02-08 14:44:53 +01:00
Bits(uint32_t value) {
this->value = value;
}
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
bool operator[](int index) {
return (value >> (N - index - 1)) & 1;
}
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:48:41 +01:00
uint32_t value{};
2018-09-24 10:43:20 +02:00
};
class ExceptionState {
public:
2022-02-08 14:44:53 +01:00
enum Type {
DSI,
ISI,
PROGRAM
};
bool isBreakpoint();
void resume();
Type type;
2022-02-08 14:48:41 +01:00
OSContext context{};
2022-02-08 14:44:53 +01:00
2022-02-08 14:48:41 +01:00
OSThread *thread{};
2022-02-08 14:44:53 +01:00
2022-02-08 14:48:41 +01:00
OSMessageQueue queue{};
OSMessage message{};
2022-02-08 14:44:53 +01:00
2022-02-08 14:48:41 +01:00
bool isPaused{};
2018-09-24 10:43:20 +02:00
};
class ExceptionMgr {
public:
2022-02-08 14:44:53 +01:00
void init();
void lock();
void unlock();
void cleanup();
ExceptionState *find(OSThread *thread);
ExceptionState *findOrCreate(OSThread *thread);
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:44:53 +01:00
OSMutex mutex;
std::vector<ExceptionState *> list;
2018-09-24 10:43:20 +02:00
};
class BreakPoint {
public:
2022-02-08 14:48:41 +01:00
bool isRange(uint32_t addr, uint32_t length) const;
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
uint32_t address;
uint32_t instruction;
bool isSpecial;
2018-09-24 10:43:20 +02:00
};
class SpecialBreakPoint : public BreakPoint {
public:
2022-02-08 14:44:53 +01:00
OSThread *thread;
2018-09-24 10:43:20 +02:00
};
2022-02-08 14:44:53 +01:00
template<class T>
2018-09-24 10:43:20 +02:00
class BreakPointList {
public:
2022-02-08 14:44:53 +01:00
size_t size() {
return list.size();
}
T *alloc() {
2022-02-08 14:48:41 +01:00
for (size_t i = 0; i < size(); i++) {
2022-02-08 14:44:53 +01:00
if (list[i].address == 0) {
return &list[i];
}
}
T newBp;
newBp.address = 0;
newBp.instruction = 0;
list.push_back(newBp);
return &list.back();
}
T *find(uint32_t addr) {
2022-02-08 14:48:41 +01:00
for (size_t i = 0; i < size(); i++) {
2022-02-08 14:44:53 +01:00
if (list[i].address == addr) {
return &list[i];
}
}
return nullptr;
}
T *findRange(uint32_t addr, uint32_t length, int *index) {
2022-02-08 14:48:41 +01:00
size_t i = *index;
2022-02-08 14:44:53 +01:00
while (i < size()) {
if (list[i].isRange(addr, length)) {
2022-02-08 14:48:41 +01:00
*index = (int) i + 1;
2022-02-08 14:44:53 +01:00
return &list[i];
}
i++;
}
2022-02-08 14:48:41 +01:00
if ((int) i > *index) {
*index = (int) i;
2022-02-08 14:44:53 +01:00
}
return nullptr;
}
T *operator[](int index) {
return &list[index];
}
void cleanup() {
2022-02-08 14:48:41 +01:00
for (size_t i = 0; i < size(); i++) {
2022-02-08 14:44:53 +01:00
if (list[i].address != 0) {
KernelWriteU32(list[i].address, list[i].instruction);
list[i].address = 0;
list[i].instruction = 0;
}
}
}
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:44:53 +01:00
std::vector<T> list;
2018-09-24 10:43:20 +02:00
};
class BreakPointMgr {
public:
2022-02-08 14:44:53 +01:00
void init();
void lock();
void unlock();
void cleanup();
bool isCustom(uint32_t addr);
bool isSoftware(uint32_t addr);
bool isSpecial(uint32_t addr);
void read(void *buffer, uint32_t addr, uint32_t length);
void write(const void *buffer, uint32_t addr, uint32_t length);
void toggle(uint32_t addr);
uint32_t getInstr(uint32_t addr);
BreakPoint *find(uint32_t addr, bool includeSpecial);
BreakPoint *findRange(uint32_t addr, uint32_t length, int *index, bool includeSpecial);
SpecialBreakPoint *findSpecial(uint32_t addr, OSThread *thread);
void clearSpecial(OSThread *thread);
void predictStep(ExceptionState *state, bool stepOver);
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:44:53 +01:00
BreakPoint *alloc();
SpecialBreakPoint *allocSpecial();
void disable(BreakPoint *bp);
void enable(BreakPoint *bp, uint32_t addr);
BreakPointList<BreakPoint> breakpoints;
BreakPointList<SpecialBreakPoint> special;
2022-02-08 14:48:41 +01:00
OSMutex mutex{};
2018-09-24 10:43:20 +02:00
};
class StepMgr {
public:
2022-02-08 14:44:53 +01:00
void init();
void lock();
void unlock();
void singleStep(ExceptionState *state, uint32_t instruction);
void handleBreakPoint(ExceptionState *state);
void adjustAddress(ExceptionState *state);
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:44:53 +01:00
static uint32_t buffer[96];
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
uint32_t *alloc();
void free(int index);
2022-02-08 14:48:41 +01:00
static void branchConditional(ExceptionState *state, uint32_t instruction, uint32_t target, bool checkCtr);
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
OSMutex mutex;
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
uint32_t usedMask;
2018-09-24 10:43:20 +02:00
};
class Debugger {
public:
2022-02-08 14:44:53 +01:00
enum StepCommand {
STEP_CONTINUE,
STEP_INTO,
STEP_OVER
};
2018-09-24 10:43:20 +02:00
2022-02-08 14:44:53 +01:00
void start();
2018-09-24 10:43:20 +02:00
2022-02-08 14:48:41 +01:00
~Debugger();
2018-09-24 10:43:20 +02:00
private:
2022-02-08 14:44:53 +01:00
enum Command {
COMMAND_CLOSE,
COMMAND_READ,
COMMAND_WRITE,
COMMAND_WRITE_CODE,
COMMAND_GET_MODULE_NAME,
COMMAND_GET_MODULE_LIST,
COMMAND_GET_THREAD_LIST,
COMMAND_GET_STACK_TRACE,
COMMAND_TOGGLE_BREAKPOINT,
COMMAND_POKE_REGISTERS,
COMMAND_RECEIVE_MESSAGES,
COMMAND_SEND_MESSAGE
};
2022-02-08 14:48:41 +01:00
static int threadEntry(int argc, const char **argv);
static BOOL dsiHandler(OSContext *context);
static BOOL isiHandler(OSContext *context);
static BOOL programHandler(OSContext *context);
2022-02-08 14:44:53 +01:00
static void exceptionHandler(OSContext *context, ExceptionState::Type type);
void threadFunc();
void mainLoop(Client *client);
void handleException(OSContext *context, ExceptionState::Type type);
void handleFatalCrash(OSContext *context, ExceptionState::Type type);
void handleCrash(ExceptionState *state);
void handleBreakPoint(ExceptionState *state);
void processBreakPoint(ExceptionState *state);
void resumeBreakPoint(ExceptionState *state);
StepCommand notifyBreak(ExceptionState *state);
void cleanup();
bool checkDataRead(uint32_t addr, uint32_t length);
2022-02-08 14:48:41 +01:00
OSMessageQueue eventQueue{};
OSMessage eventMessages[MESSAGE_COUNT]{};
2022-02-08 14:44:53 +01:00
2022-02-08 14:48:41 +01:00
OSThread *serverThread{};
char *serverStack{};
2022-02-08 14:44:53 +01:00
BreakPointMgr breakpoints;
ExceptionMgr exceptions;
2022-02-08 14:48:41 +01:00
StepMgr stepper{};
2022-02-08 14:44:53 +01:00
2022-02-08 14:48:41 +01:00
bool stopRunning = false;
bool initialized{};
bool connected{};
bool firstTrap{};
2018-09-24 10:43:20 +02:00
};
2022-02-08 14:48:41 +01:00
extern "C" Debugger *debugger;