diff --git a/Dockerfile b/Dockerfile index e514521..a1090ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 \ No newline at end of file diff --git a/Makefile b/Makefile index f6bcf5f..177e219 100644 --- a/Makefile +++ b/Makefile @@ -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 #------------------------------------------------------------------------------- diff --git a/src/debugger.cpp b/src/debugger.cpp index 9fbfe8d..866a372 100644 --- a/src/debugger.cpp +++ b/src/debugger.cpp @@ -9,17 +9,14 @@ #include #include #include +#include #include +#include #include -#include #include -#include #include -#include -#include - -#include #include +#include 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(addr + 0x20), reinterpret_cast(addr + length), reinterpret_cast(__os_printf),OSGetSymbolName, - static_cast(0x121)); - - for (int i = 0; i < length / 4; i++) { - DisassemblePPCOpcode(&addrAsPtr[i], - buffer, - 0x40, - OSGetSymbolName, - static_cast(0x121)); - disassemblyPrintCallback("0x%08x 0x%08x %s\n",&addrAsPtr[i],addrAsPtr[i],buffer); + if (OSIsAddressValid(reinterpret_cast(&addrAsPtr[i]))) { + DisassemblePPCOpcode(&addrAsPtr[i], buffer, 0x40, OSGetSymbolName, static_cast(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(-1), name, &length) != OS_DYNLOAD_OK){ - strncat(name, "ERROR", sizeof(name) -1); + if (OSDynLoad_GetModuleName(reinterpret_cast(-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 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"); diff --git a/src/debugger.h b/src/debugger.h index b33d577..26bbcea 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -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); diff --git a/src/kernel.cpp b/src/kernel.cpp index 98f2f56..84c8fa6 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -1,6 +1,5 @@ #include #include -#include #include void KernelWrite(uint32_t addr, const void *data, uint32_t length) { diff --git a/src/logger.h b/src/logger.h index 061d52e..ca8e5e8 100644 --- a/src/logger.h +++ b/src/logger.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -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 diff --git a/src/main.cpp b/src/main.cpp index 584973f..1e4d62b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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() { diff --git a/src/menu.cpp b/src/menu.cpp deleted file mode 100644 index e8825cd..0000000 --- a/src/menu.cpp +++ /dev/null @@ -1,42 +0,0 @@ - -#include "menu.h" -#include "color.h" -#include "input.h" -#include - -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(); -} diff --git a/src/menu.h b/src/menu.h deleted file mode 100644 index a03d67f..0000000 --- a/src/menu.h +++ /dev/null @@ -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; -}; diff --git a/src/screen.cpp b/src/screen.cpp index 26af14e..41a8c5c 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -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);