diff --git a/core/kernel/filesystem.cpp b/core/kernel/filesystem.cpp index 6dfce6ef..fce367b2 100644 --- a/core/kernel/filesystem.cpp +++ b/core/kernel/filesystem.cpp @@ -85,7 +85,7 @@ int mmap(void* addr, size_t len, int prot, SceMap flags, int fd, int64_t offset, } if (flags.type == SceMapType::ANON) { - int result = accessMemoryManager()->flexibleMemory()->alloc((uint64_t)addr, len, prot, (uint64_t*)*res); // registers mapping (flexible) + int result = accessMemoryManager()->flexibleMemory()->map((uint64_t)addr, 0, len, prot, (int&)flags, 0, (uint64_t*)*res); // registers mapping (flexible) LOG_DEBUG(L"Mmap anon addr:0x%08llx len:0x%08llx prot:%d flags:%d fd:%d offset:%lld -> out:0x%08llx", addr, len, prot, flags, fd, offset, *res); return result; diff --git a/core/runtime/util/exceptionHandler.cpp b/core/runtime/util/exceptionHandler.cpp index 47d37bf3..74f00b4a 100644 --- a/core/runtime/util/exceptionHandler.cpp +++ b/core/runtime/util/exceptionHandler.cpp @@ -1,14 +1,97 @@ #include "exceptionHandler.h" +#include "../runtimeLinker.h" #include "logging.h" +#include #include #include + +// clang-format off #include +#include +// clang-format on LOG_DEFINE_MODULE(ExceptionHandler); namespace { + +std::optional> findModule(uint64_t address) { + std::unordered_map modules; + + HANDLE hProcess = GetCurrentProcess(); + HMODULE hModules[1024]; + DWORD cbNeeded; + + if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) { + MODULEINFO mi; + + for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { + GetModuleInformation(hProcess, hModules[i], &mi, sizeof(mi)); + + if ((uint64_t)mi.lpBaseOfDll <= address && address < ((uint64_t)mi.lpBaseOfDll + mi.SizeOfImage)) { + char moduleName[MAX_PATH]; + if (GetModuleFileName(hModules[i], moduleName, MAX_PATH)) { + return std::make_pair((uint64_t)mi.lpBaseOfDll, std::string(moduleName)); + } + } + } + } + + auto prog = accessRuntimeLinker().findProgram(address); + if (prog != nullptr) { + return std::make_pair(prog->baseVaddr, prog->filename.string()); + } + + return std::nullopt; +} + +void stackTrace(uint64_t addr) { + LOG_USE_MODULE(ExceptionHandler); + + bool foundStart = false; + size_t countTraces = 0; + + // Stack trace + for (auto& trace: boost::stacktrace::basic_stacktrace()) { + if (!foundStart) { + + if ((uint64_t)trace.address() == addr) + foundStart = true; + else + continue; + } + if (++countTraces > 4) break; + + if (trace.empty()) { + LOG_ERR(L"????"); + } + + std::string fileName; + int lineNumber = 0; + DWORD displacement = 0; + + auto optModuleInfo = findModule((uint64_t)trace.address()); + + if (fileName.empty()) { + auto optModuleInfo = findModule((uint64_t)trace.address()); + + if (optModuleInfo) { + LOG_ERR(L"offset:0x%08llx\t base:0x%08llx\t%S", (uint64_t)trace.address() - optModuleInfo->first, optModuleInfo->first, optModuleInfo->second.c_str()); + } else { + LOG_ERR(L"0x%08llx\t", trace.address()); + } + } else { + if (optModuleInfo) { + LOG_ERR(L"0x%08llx\t %S at %llu base:0x%08llx %S", trace.address(), fileName.c_str(), lineNumber, optModuleInfo->first, optModuleInfo->second.c_str()); + } else { + LOG_ERR(L"0x%08llx\t %S at %llu", trace.address(), fileName.c_str(), lineNumber); + } + } + } + // - +} + enum class AccessViolationType { Unknown, Read, Write, Execute }; LONG WINAPI DefaultExceptionHandler(PEXCEPTION_POINTERS exception) { @@ -19,16 +102,28 @@ LONG WINAPI DefaultExceptionHandler(PEXCEPTION_POINTERS exception) { auto exceptionAddr = (uint64_t)(exceptionRecord->ExceptionAddress); auto violationAddr = exceptionRecord->ExceptionInformation[1]; + stackTrace(exceptionAddr); + + uint64_t baseAddr = 0; + std::string moduleName; + + auto optModuleInfo = findModule(exceptionAddr); + if (optModuleInfo) { + baseAddr = optModuleInfo->first; + moduleName = optModuleInfo->second; + } + AccessViolationType violationType; switch (exceptionRecord->ExceptionInformation[0]) { case 0: violationType = AccessViolationType::Read; break; case 1: violationType = AccessViolationType::Write; break; case 8: violationType = AccessViolationType::Execute; break; - default: LOG_CRIT(L"unknown exception at 0x%08llx", exceptionAddr); break; + default: LOG_CRIT(L"unknown exception at 0x%08llx, module base:0x%08llx %S", exceptionAddr, baseAddr, moduleName.data()); break; } - LOG_CRIT(L"Access violation: %S at addr:0x%08llx info:0x%08llx", magic_enum::enum_name(violationType).data(), exceptionAddr, violationAddr); - //(violationVaddr == accessRuntimeLinker().getAddrInvalidMemory() ? L"(Unpatched object)" : L"")); + LOG_CRIT(L"Access violation: %S at addr:0x%08llx info:0x%08llx %S, module base:0x%08llx %S", magic_enum::enum_name(violationType).data(), exceptionAddr, + violationAddr, (violationAddr == accessRuntimeLinker().getAddrInvalidMemory() ? L"(Unpatched object)" : L""), baseAddr, moduleName.data()); + //); return EXCEPTION_CONTINUE_EXECUTION; } diff --git a/core/runtime/util/exceptionHandler.h b/core/runtime/util/exceptionHandler.h index 9265c9b8..e8476c5e 100644 --- a/core/runtime/util/exceptionHandler.h +++ b/core/runtime/util/exceptionHandler.h @@ -5,4 +5,5 @@ namespace ExceptionHandler { std::unique_ptr install(uint64_t imageAddr, uint64_t imageSize); + } // namespace ExceptionHandler \ No newline at end of file diff --git a/core/videoout/vulkan/vulkanSetup.cpp b/core/videoout/vulkan/vulkanSetup.cpp index 7e3f8693..b8226892 100644 --- a/core/videoout/vulkan/vulkanSetup.cpp +++ b/core/videoout/vulkan/vulkanSetup.cpp @@ -26,10 +26,10 @@ namespace vulkan { struct VulkanExtensions { bool enableValidationLayers = true; - std::vector requiredExtensions; + std::list requiredExtensions; std::vector availableExtensions; - std::vector requiredLayers; + std::list requiredLayers; std::vector availableLayers; }; @@ -118,7 +118,9 @@ VulkanExtensions getExtensions(SDL_Window* window, bool enableValidation) { VulkanExtensions r = {.enableValidationLayers = enableValidation}; SDL_Vulkan_GetInstanceExtensions(window, &countRequiredExtensions, NULL); + auto extensions = static_cast(SDL_malloc(sizeof(char*) * countRequiredExtensions)); + SDL_Vulkan_GetInstanceExtensions(window, &countRequiredExtensions, extensions); for (size_t n = 0; n < countRequiredExtensions; n++) { r.requiredExtensions.push_back(extensions[n]); @@ -136,8 +138,8 @@ VulkanExtensions getExtensions(SDL_Window* window, bool enableValidation) { r.enableValidationLayers = false; } - for (size_t n = 0; n < r.requiredExtensions.size(); ++n) { - LOG_INFO(L"SDL2 required extension: %S", r.requiredExtensions[n]); + for (auto& ext: r.requiredExtensions) { + LOG_INFO(L"SDL2 required extension: %S", ext.c_str()); } for (const auto& ext: r.availableExtensions) { @@ -156,8 +158,9 @@ VulkanExtensions getExtensions(SDL_Window* window, bool enableValidation) { if (r.enableValidationLayers) { r.requiredLayers.push_back("VK_LAYER_KHRONOS_validation"); for (auto const l: r.requiredLayers) { - if (std::find_if(r.availableLayers.begin(), r.availableLayers.end(), [&l](auto s) { return strcmp(s.layerName, l) == 0; }) == r.availableLayers.end()) { - LOG_INFO(L"no validation layer:%S", l); + if (std::find_if(r.availableLayers.begin(), r.availableLayers.end(), [&l](auto s) { return strcmp(s.layerName, l.c_str()) == 0; }) == + r.availableLayers.end()) { + LOG_INFO(L"no validation layer:%S", l.c_str()); r.enableValidationLayers = false; break; } @@ -651,14 +654,21 @@ VkDevice createDevice(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, Vul .provokingVertexLast = VK_TRUE, }; + std::vector reqLayers; + reqLayers.reserve(1 + extensions.requiredLayers.size()); + + for (auto& req: extensions.requiredLayers) { + reqLayers.push_back(req.c_str()); + } + VkDeviceCreateInfo const createInfo { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &provVertex, .flags = 0, .queueCreateInfoCount = numQueueCreateInfo, .pQueueCreateInfos = queueCreateInfo.data(), - .enabledLayerCount = (uint32_t)extensions.requiredLayers.size(), - .ppEnabledLayerNames = extensions.requiredLayers.data(), + .enabledLayerCount = (uint32_t)reqLayers.size(), + .ppEnabledLayerNames = reqLayers.data(), .enabledExtensionCount = requiredExtensions.size(), .ppEnabledExtensionNames = requiredExtensions.data(), .pEnabledFeatures = &deviceFeatures, @@ -696,22 +706,36 @@ VulkanObj* initVulkan(SDL_Window* window, VkSurfaceKHR& surface, bool enableVali .pNext = nullptr, .pApplicationName = "psOff", .applicationVersion = 1, - .pEngineName = "psEngine", + .pEngineName = "psOff_render", .engineVersion = 1, .apiVersion = VK_API_VERSION_1_3, }; auto extensions = getExtensions(window, enableValidation); + std::vector reqLayers; + reqLayers.reserve(1 + extensions.requiredLayers.size()); + + for (auto& req: extensions.requiredLayers) { + reqLayers.push_back(req.c_str()); + } + + std::vector reqExt; + reqExt.reserve(1 + extensions.requiredLayers.size()); + + for (auto& req: extensions.requiredExtensions) { + reqExt.push_back(req.c_str()); + } + VkInstanceCreateInfo const instInfo { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = extensions.enableValidationLayers ? &dbgCreateInfo : nullptr, .flags = 0, .pApplicationInfo = &appInfo, - .enabledLayerCount = (uint32_t)extensions.requiredLayers.size(), - .ppEnabledLayerNames = extensions.requiredLayers.data(), - .enabledExtensionCount = (uint32_t)extensions.requiredExtensions.size(), - .ppEnabledExtensionNames = extensions.requiredExtensions.data(), + .enabledLayerCount = (uint32_t)reqLayers.size(), + .ppEnabledLayerNames = reqLayers.data(), + .enabledExtensionCount = (uint32_t)reqExt.size(), + .ppEnabledExtensionNames = reqExt.data(), }; if (VkResult result = vkCreateInstance(&instInfo, nullptr, &obj->deviceInfo->instance); result != VK_SUCCESS) { diff --git a/core/videoout/vulkan/vulkanSetup.h b/core/videoout/vulkan/vulkanSetup.h index 3bb8cedc..bbcfae12 100644 --- a/core/videoout/vulkan/vulkanSetup.h +++ b/core/videoout/vulkan/vulkanSetup.h @@ -63,11 +63,13 @@ struct SurfaceCapabilities { }; struct VulkanObj { - std::shared_ptr deviceInfo = std::make_shared(); + std::shared_ptr deviceInfo; VkDebugUtilsMessengerEXT debugMessenger = nullptr; SurfaceCapabilities surfaceCapabilities; Queues queues; + + VulkanObj() { deviceInfo = std::make_shared(); } }; VulkanObj* initVulkan(SDL_Window* window, VkSurfaceKHR& surface, bool useValidation); diff --git a/modules/libkernel/entry.cpp b/modules/libkernel/entry.cpp index af00c955..7f16e58b 100644 --- a/modules/libkernel/entry.cpp +++ b/modules/libkernel/entry.cpp @@ -318,10 +318,7 @@ EXPORT SYSV_ABI void _sceKernelRtldSetApplicationHeapAPI(void* api[]) { } EXPORT SYSV_ABI void sceKernelDebugRaiseException(int reason, int id) { - LOG_USE_MODULE(libkernel); - - auto const retAddr = (uint64_t)_ReturnAddress(); - LOG_CRIT(L"Exception: reason:0x%x id:0x%x @0x%08llx", reason, id, retAddr); + RaiseException(id, reason, 0, 0); } EXPORT SYSV_ABI int __NID(__elf_phdr_match_addr)(SceKernelModuleInfoEx* m, uint64_t dtor_vaddr) {