diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f50d30d8..26af60519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,22 @@ if (PROJECT_IS_TOP_LEVEL) if (SUPPORTS_W_NO_EVERYTHING) target_compile_options(geode-loader PRIVATE -Wno-inconsistent-missing-override) endif() + # On windows, prepare "CodegenData.txt" for embedding it into the binary (used for crashlog symbols) + if (WIN32) + file(STRINGS ${CMAKE_BINARY_DIR}/bindings/bindings/Geode/CodegenData.txt CODEGEN_DATA) + set(CODEGEN_DATA_INCLUDE "#pragma once\n#include \n\nstatic std::unordered_map s_codegenData = {\n") + foreach(line IN LISTS CODEGEN_DATA) + string(REGEX MATCH "([a-zA-Z0-9:_]+) - 0x([0-9a-fA-F]+)" MATCHED ${line}) + if (NOT MATCHED) + continue() + endif() + set(FUNC_NAME ${CMAKE_MATCH_1}) + set(FUNC_ADDR ${CMAKE_MATCH_2}) + set(CODEGEN_DATA_INCLUDE "${CODEGEN_DATA_INCLUDE}\t{0x${FUNC_ADDR}, \"${FUNC_NAME}\"},\n") + endforeach() + set(CODEGEN_DATA_INCLUDE "${CODEGEN_DATA_INCLUDE}}\;") + file(WRITE ${CMAKE_BINARY_DIR}/bindings/bindings/Geode/CodegenData.hpp ${CODEGEN_DATA_INCLUDE}) + endif() elseif (EXISTS ${GEODE_PLATFORM_BIN_PATH}) target_link_libraries(${PROJECT_NAME} INTERFACE "${GEODE_PLATFORM_BIN_PATH}") if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS) diff --git a/loader/src/platform/windows/crashlog.cpp b/loader/src/platform/windows/crashlog.cpp index c3c5be27a..4a06ac16c 100644 --- a/loader/src/platform/windows/crashlog.cpp +++ b/loader/src/platform/windows/crashlog.cpp @@ -19,6 +19,7 @@ #include #include #include "ehdata_structs.hpp" +#include using namespace geode::prelude; @@ -90,6 +91,18 @@ static Mod* modFromAddress(PVOID exceptionAddress) { return nullptr; } +static uintptr_t findMethodStart(void const* address, size_t maxSearch = 0x1000) { + // Backtrack until we hit a 0xCC (int3) instruction + uintptr_t start = reinterpret_cast(address); + while (start > reinterpret_cast(address) - maxSearch) { + if (*reinterpret_cast(start) == 0xCC) { + return start + 1; + } + start--; + } + return reinterpret_cast(address); +} + static void printAddr(std::ostream& stream, void const* addr, bool fullPath = true) { HMODULE module = nullptr; @@ -135,6 +148,21 @@ static void printAddr(std::ostream& stream, void const* addr, bool fullPath = tr } stream << ")"; + } else if (module == GetModuleHandle(nullptr)) { + uintptr_t methodStart = findMethodStart(addr); + if (methodStart == reinterpret_cast(addr)) { + return; + } + + uintptr_t baseOffset = methodStart - reinterpret_cast(module); + uintptr_t methodOffset = reinterpret_cast(addr) - methodStart; + + auto it = s_codegenData.find(baseOffset); + if (it != s_codegenData.end()) { + stream << " (" << it->second << " + " << std::hex << methodOffset << std::dec << ")"; + } else { + stream << " ( + " << methodOffset << std::dec << ")"; + } } } }