This commit is contained in:
Maschell 2023-01-27 16:59:46 +01:00
parent 60a0679699
commit cda1a77ec8
10 changed files with 110 additions and 176 deletions

View File

@ -1,6 +1,7 @@
FROM wiiuenv/devkitppc:20211229
FROM wiiuenv/devkitppc:20220724
COPY --from=wiiuenv/wiiupluginsystem:20220123 /artifacts $DEVKITPRO
COPY --from=wiiuenv/libiosuhax:20220129 /artifacts $DEVKITPRO
COPY --from=wiiuenv/wiiupluginsystem:20220724 /artifacts $DEVKITPRO
COPY --from=wiiuenv/libkernel:20220724 /artifacts $DEVKITPRO
COPY --from=wiiuenv/libmappedmemory:20220724 /artifacts $DEVKITPRO
WORKDIR project

View File

@ -39,10 +39,10 @@ CXXFLAGS := $(CFLAGS)
ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libmappedmemory.ld -T$(WUMS_ROOT)/share/libkernel.ld $(WUPSSPECS)
ifeq ($(DEBUG),1)
CXXFLAGS += -DDEBUG -g
CFLAGS += -DDEBUG -g
endif
LIBS := -lwups -lwut -lkernel -lmappedmemory
@ -103,7 +103,7 @@ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#-------------------------------------------------------------------------------

View File

@ -9,17 +9,14 @@
#include <coreinit/exception.h>
#include <coreinit/interrupts.h>
#include <coreinit/memory.h>
#include <coreinit/memorymap.h>
#include <coreinit/scheduler.h>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <gx2/context.h>
#include <malloc.h>
#include <sysapp/switch.h>
#include <vpad/input.h>
#include <stdarg.h>
#include <string>
#include <vpad/input.h>
Debugger *debugger;
bool initDebugState = false;
@ -604,10 +601,11 @@ void Debugger::handleCrash(ExceptionState *state) {
void Debugger::handleFatalCrash(OSContext *context, ExceptionState::Type type) {
const char *name;
if (type == ExceptionState::DSI) name = "A DSI";
else if (type == ExceptionState::ISI)
if (type == ExceptionState::DSI) {
name = "A DSI";
} else if (type == ExceptionState::ISI) {
name = "An ISI";
else {
} else {
name = "A program";
}
DumpContext(context, name);
@ -638,7 +636,7 @@ void Debugger::exceptionHandler(OSContext *context, ExceptionState::Type type) {
}
BOOL Debugger::dsiHandler(OSContext *context) {
OSContext *info = new OSContext();
auto *info = new OSContext();
memcpy(info, context, sizeof(OSContext));
context->srr0 = (uint32_t) exceptionHandler;
context->gpr[3] = (uint32_t) info;
@ -673,64 +671,41 @@ void Debugger::cleanup() {
;
}
static const char **commandNames = (const char *[]){
"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",
"COMMAND_DISASM"};
#define LOG_DISASSEMBLY_SIZE (4096)
static char
sDisassemblyBuffer[LOG_DISASSEMBLY_SIZE];
static char sDisassemblyBuffer[LOG_DISASSEMBLY_SIZE];
static uint32_t
sDisassemblyLength = 0;
static uint32_t sDisassemblyLength = 0;
static void
disassemblyPrintCallback(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
sDisassemblyLength += vsprintf(sDisassemblyBuffer + sDisassemblyLength,
fmt, args);
sDisassemblyLength += vsprintf(sDisassemblyBuffer + sDisassemblyLength, fmt, args);
sDisassemblyBuffer[sDisassemblyLength] = 0;
va_end(args);
}
void eraseAllSubStr(std::string & mainStr, const std::string & toErase)
{
void eraseAllSubStr(std::string &mainStr, const std::string &toErase) {
size_t pos = std::string::npos;
// Search for the substring in string in a loop untill nothing is found
while ((pos = mainStr.find(toErase) )!= std::string::npos)
{
// Search for the substring in string in a loop until nothing is found
while ((pos = mainStr.find(toErase)) != std::string::npos) {
// If found then erase it from string
mainStr.erase(pos, toErase.length());
}
}
//#define OSIopShell_Command_Disassemble ((void (*)(void*, uint32_t))(0x101C400 + 0x173e0))
#define __os_printf ((void (*)(char*, ...))(0x101C400 + 0x012e88))
#define __os_printf ((void (*)(char *, ...))(0x101C400 + 0x012e88))
void Debugger::mainLoop(Client *client) {
while (!stopRunning) {
uint8_t cmd;
if (!client->recvall(&cmd, 1)) return;
if (cmd <= 12 && cmd != 10) {
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
if (!client->recvall(&cmd, 1)) {
return;
}
if (cmd == COMMAND_CLOSE) {
return;
} else if (cmd == COMMAND_READ) {
@ -755,36 +730,25 @@ void Debugger::mainLoop(Client *client) {
auto addrAsPtr = (uint32_t *) (addr & 0xfffffffc);
DisassemblePPCRange(reinterpret_cast<void *>(addr + 0x20), reinterpret_cast<void *>(addr + length), reinterpret_cast<DisassemblyPrintFn>(__os_printf),OSGetSymbolName,
static_cast<DisassemblePPCFlags>(0x121));
for (int i = 0; i < length / 4; i++) {
DisassemblePPCOpcode(&addrAsPtr[i],
buffer,
0x40,
OSGetSymbolName,
static_cast<DisassemblePPCFlags>(0x121));
disassemblyPrintCallback("0x%08x 0x%08x %s\n",&addrAsPtr[i],addrAsPtr[i],buffer);
if (OSIsAddressValid(reinterpret_cast<uint32_t>(&addrAsPtr[i]))) {
DisassemblePPCOpcode(&addrAsPtr[i], buffer, 0x40, OSGetSymbolName, static_cast<DisassemblePPCFlags>(0x121));
disassemblyPrintCallback("0x%08x 0x%08x %s\n", &addrAsPtr[i], addrAsPtr[i], buffer);
} else {
disassemblyPrintCallback("0x%08x ?????????? ???\n", &addrAsPtr[i]);
}
}
delete[] buffer;
std::string tmpString(sDisassemblyBuffer);
eraseAllSubStr(tmpString, "(null)");
std::string shit(sDisassemblyBuffer);
eraseAllSubStr(shit, "(null)");
DEBUG_FUNCTION_LINE("done");
auto length_ = shit.length() + 1;
auto length_ = tmpString.length() + 1;
if (!client->sendall(&length_, 4)) {
sDisassemblyLength = 0;
return;
}
if (!client->sendall(shit.c_str(), length_)) {
if (!client->sendall(tmpString.c_str(), length_)) {
sDisassemblyLength = 0;
return;
}
@ -809,36 +773,44 @@ void Debugger::mainLoop(Client *client) {
} else if (cmd == COMMAND_GET_MODULE_NAME) {
char name[0x40];
int length = 0x40;
if(OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length) != OS_DYNLOAD_OK){
strncat(name, "ERROR", sizeof(name) -1);
if (OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length) != OS_DYNLOAD_OK) {
strncat(name, "ERROR", sizeof(name) - 1);
}
length = strlen(name);
if (!client->sendall(&length, 4)) return;
if (!client->sendall(name, length)) return;
} else if (cmd == COMMAND_GET_MODULE_LIST) {
int num_rpls = OSDynLoad_GetNumberOfRPLs();
if (num_rpls == 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to get OSDynLoad_GetNumberOfRPLs");
continue;
}
std::vector<OSDynLoad_NotifyData> rpls;
rpls.resize(num_rpls);
bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
if (!ret) {
DEBUG_FUNCTION_LINE_ERR("Failed to get OSDynLoad_GetRPLInfo");
continue;
}
auto BUFFER_SIZE = 0x1000; //This should be enough
char buffer[BUFFER_SIZE];
char buffer[0x1000]; //This should be enough
uint32_t offset = 0;
for (auto &info : rpls) {
uint32_t namelen = strlen(info.name);
if (offset + 0x18 + namelen > 0x1000) {
uint32_t namelen = 0;
if (info.name != nullptr) {
namelen = strlen(info.name);
}
if (offset + 0x18 + namelen > BUFFER_SIZE) {
break;
}
auto *infobuf = (uint32_t *) (buffer + offset);
infobuf[0] = info.textAddr;
infobuf[1] = info.textSize;
@ -846,31 +818,32 @@ void Debugger::mainLoop(Client *client) {
infobuf[3] = info.dataSize;
infobuf[4] = (uint32_t) 0; // TODO: missing
infobuf[5] = namelen;
memcpy(&infobuf[6], info.name, namelen);
offset += 0x18 + strlen(info.name);
if (namelen > 0) {
memcpy(&infobuf[6], info.name, namelen);
offset += 0x18 + strlen(info.name);
}
}
//OSUnlockMutex(OSDynLoad_gLoaderLock);
if (!client->sendall(&offset, 4)) return;
if (!client->sendall(buffer, offset)) return;
} else if (cmd == COMMAND_GET_THREAD_LIST) {
int state = OSDisableInterrupts();
__OSLockScheduler(this);
char buffer[0x1000]; //This should be enough
auto BUFFER_SIZE = 0x1000; //This should be enough
char buffer[BUFFER_SIZE]; //This should be enough
uint32_t offset = 0;
OSThread *current = ThreadList;
while (current) {
const char *name = OSGetThreadName(current);
OSReport("name %s", name);
uint32_t namelen = 0;
if (name) {
namelen = strlen(name);
}
if (offset + 0x1C + namelen > 0x1000) {
if (offset + 0x1C + namelen > BUFFER_SIZE) {
break;
}
@ -978,7 +951,7 @@ void Debugger::mainLoop(Client *client) {
}
exceptions.unlock();
} else {
DEBUG_FUNCTION_LINE("Recieved unknown command %d", cmd);
DEBUG_FUNCTION_LINE_ERR("Recieved unknown command %d", cmd);
}
}
}
@ -1027,7 +1000,7 @@ void Debugger::start() {
serverStack = (char *) memalign(0x20, STACK_SIZE);
OSCreateThread(
serverThread, threadEntry, 0, 0,
serverThread, threadEntry, 0, nullptr,
serverStack + STACK_SIZE, STACK_SIZE,
0, OS_THREAD_ATTRIB_AFFINITY_CPU2 | OS_THREAD_ATTRIB_DETACHED);
OSSetThreadName(serverThread, "Debug Server");

View File

@ -222,7 +222,7 @@ public:
~Debugger();
private:
enum Command {
typedef enum Command {
COMMAND_CLOSE,
COMMAND_READ,
COMMAND_WRITE,
@ -236,7 +236,7 @@ private:
COMMAND_RECEIVE_MESSAGES,
COMMAND_SEND_MESSAGE,
COMMAND_DISASM
};
} Command;
static int threadEntry(int argc, const char **argv);
static BOOL dsiHandler(OSContext *context);

View File

@ -1,6 +1,5 @@
#include <coreinit/cache.h>
#include <coreinit/memorymap.h>
#include <cstdint>
#include <kernel/kernel.h>
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {

View File

@ -1,5 +1,6 @@
#pragma once
#include <coreinit/debug.h>
#include <string.h>
#include <whb/log.h>
@ -7,30 +8,52 @@
extern "C" {
#endif
#define LOG_APP_TYPE "P"
#define LOG_APP_NAME "debugger_plugin"
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX_DEFAULT(LOG_FUNC, "", "", FMT, ##ARGS)
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
do { \
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
} while (0)
#ifdef DEBUG
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
#ifdef VERBOSE_DEBUG
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "", "", FMT, ##ARGS);
#else
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
#endif
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) \
do { \
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) \
do { \
WHBLogWritef("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0)
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS);
#else
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);
#endif

View File

@ -21,15 +21,15 @@ WUPS_USE_WUT_DEVOPTAB();
/* https://github.com/QuarkTheAwesome/CafeBinPatch/blob/main/src/runtime-patcher.cpp#L58 */
bool PatchInstruction(void *instr, uint32_t original, uint32_t replacement) {
uint32_t current = *(uint32_t *) instr;
if (current != original) return current == replacement;
if (current != original) {
return current == replacement;
}
KernelCopyData(OSEffectiveToPhysical((uint32_t) instr), OSEffectiveToPhysical((uint32_t) &replacement), sizeof(replacement));
//Only works on AROMA! WUPS 0.1's KernelCopyData is uncached, needs DCInvalidate here instead
DCFlushRange(instr, 4);
ICInvalidateRange(instr, 4);
current = *(uint32_t *) instr;
return true;
}
@ -55,20 +55,20 @@ INITIALIZE_PLUGIN() {
ON_APPLICATION_START() {
initLogging();
DEBUG_FUNCTION_LINE("Hello from Debugger plugin");
pThreadList = (OSThread **) 0x100567F8; // 100567f8
debugger = new Debugger();
DCFlushRange(&debugger, 4);
DCFlushRange(debugger, sizeof(Debugger));
DEBUG_FUNCTION_LINE("Created Debugger");
OSMemoryBarrier();
DEBUG_FUNCTION_LINE_VERBOSE("Created Debugger");
debugger->start();
DEBUG_FUNCTION_LINE("Started Debugger thread");
DEBUG_FUNCTION_LINE_VERBOSE("Started Debugger thread");
}
ON_APPLICATION_REQUESTS_EXIT() {
DEBUG_FUNCTION_LINE("Deleting Debugger thread");
DEBUG_FUNCTION_LINE_VERBOSE("Deleting Debugger thread");
delete debugger;
DEBUG_FUNCTION_LINE("Deleted Debugger thread");
DEBUG_FUNCTION_LINE_VERBOSE("Deleted Debugger thread");
deinitLogging();
}
ON_APPLICATION_ENDS() {

View File

@ -1,42 +0,0 @@
#include "menu.h"
#include "color.h"
#include "input.h"
#include <vpad/input.h>
Menu::Menu(Screen *screen) : screen(screen) {
currentOption = LaunchDisk;
message = nullptr;
}
Menu::Option Menu::show() {
while (true) {
redraw();
uint32_t buttons = WaitInput(VPAD_BUTTON_A | VPAD_BUTTON_DOWN | VPAD_BUTTON_UP);
if (buttons & VPAD_BUTTON_A) return (Option) currentOption;
else if (buttons & VPAD_BUTTON_DOWN) {
if (currentOption < 2) currentOption++;
} else if (buttons & VPAD_BUTTON_UP) {
if (currentOption > 0) currentOption--;
}
}
}
void Menu::setMessage(const char *message) {
this->message = message;
redraw();
}
void Menu::redraw() {
screen->clear(COLOR_BLUE);
Screen::drawText(5, 5, "Wii U Debugger");
Screen::drawText(5, 7, "Choose an option:");
Screen::drawText(8, 9, "Install and launch disc");
Screen::drawText(8, 10, "Install and return to system menu");
Screen::drawText(8, 11, "Exit without installing");
Screen::drawText(5, 9 + currentOption, ">");
if (message) {
Screen::drawText(5, 13, message);
}
Screen::flip();
}

View File

@ -1,22 +0,0 @@
#pragma once
#include "screen.h"
class Menu {
public:
enum Option { LaunchDisk,
ReturnToMenu,
Exit };
Menu(Screen *screen);
Option show();
void setMessage(const char *message);
void redraw();
private:
Screen *screen;
int currentOption;
const char *message;
};

View File

@ -19,9 +19,11 @@ void Screen::init() {
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
if (screenBuffer == nullptr) {
OSFatal("Failed to allocate screenbuffer");
}
memset(screenBuffer, 0, bufferSize0 + bufferSize1);
OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);