import sys p = r"C:/Users/locpham/SonicForgeStudio/native_bridge/src/main.cpp" data = open(p, "rb").read() def rep(old, new, count=1): global data old = old.encode(); new = new.encode() assert data.count(old) >= count, "pattern not found: %r" % old data = data.replace(old, new, count) # unwind stack from exception context BEFORE the dump writer clobbers it stackdump = r""" // Unwind the LIVE stack from the exception context (MiniDumpWriteDump captures // the context at dump time, not at raise time — by then the handler's own // frames replace the real ones). Print return-address candidates that land in // loaded modules, lowest stack address first. #ifdef _WIN32 static void DumpStackTraceFromContext(const CONTEXT* ctx) { if (!ctx) return; std::cerr << "[VCRASH] stack trace (raw scan):" << std::endl; const unsigned char* sp = (const unsigned char*)ctx->Rsp; for (int i = 0; i < 512; i++) { uintptr_t val = 0; memcpy(&val, sp + i * 8, sizeof(val)); // stack is readable in a handler HMODULE h = nullptr; char m[MAX_PATH] = {0}; if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)val, &h) && h && GetModuleFileNameA(h, m, MAX_PATH)) { const char* base = strrchr(m, '\\'); base = base ? base + 1 : m; std::cerr << " +" << i * 8 << " " << (void*)val << " " << base << "+0x" << std::hex << (val - (uintptr_t)h) << std::dec << std::endl; } } } #endif """ rep("static LONG WINAPI VectoredCrashHandler(PEXCEPTION_POINTERS ep) {", stackdump + "\nstatic LONG WINAPI VectoredCrashHandler(PEXCEPTION_POINTERS ep) {") # call it right at handler entry rep(""" std::cerr << "[VCRASH] first-chance code=0x" << std::hex << code << " addr=0x" << (er ? (void*)er->ExceptionAddress : nullptr) << std::dec << " tid=" << GetCurrentThreadId() << std::endl;""", """ std::cerr << "[VCRASH] first-chance code=0x" << std::hex << code << " addr=0x" << (er ? (void*)er->ExceptionAddress : nullptr) << std::dec << " tid=" << GetCurrentThreadId() << std::endl; DumpStackTraceFromContext(ep ? ep->ContextRecord : nullptr);""") open(p, "wb").write(data) print("patched OK, size=", len(data))