Skip to content

Commit

Permalink
Merge pull request #143 from SysRay/work
Browse files Browse the repository at this point in the history
vulkanSetup fixes, + exception(more infos)
  • Loading branch information
SysRay authored Apr 30, 2024
2 parents 1dd94fc + 9c3e73c commit bd26687
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 22 deletions.
2 changes: 1 addition & 1 deletion core/kernel/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
101 changes: 98 additions & 3 deletions core/runtime/util/exceptionHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,97 @@
#include "exceptionHandler.h"

#include "../runtimeLinker.h"
#include "logging.h"

#include <boost/stacktrace.hpp>
#include <magic_enum/magic_enum.hpp>
#include <mutex>

// clang-format off
#include <windows.h>
#include <psapi.h>
// clang-format on

LOG_DEFINE_MODULE(ExceptionHandler);

namespace {

std::optional<std::pair<uint64_t, std::string>> findModule(uint64_t address) {
std::unordered_map<uint64_t, std::string> 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) {
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions core/runtime/util/exceptionHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
namespace ExceptionHandler {

std::unique_ptr<uint8_t[]> install(uint64_t imageAddr, uint64_t imageSize);

} // namespace ExceptionHandler
50 changes: 37 additions & 13 deletions core/videoout/vulkan/vulkanSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ namespace vulkan {
struct VulkanExtensions {
bool enableValidationLayers = true;

std::vector<const char*> requiredExtensions;
std::list<std::string> requiredExtensions;

std::vector<VkExtensionProperties> availableExtensions;
std::vector<const char*> requiredLayers;
std::list<std::string> requiredLayers;
std::vector<VkLayerProperties> availableLayers;
};

Expand Down Expand Up @@ -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<const char**>(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]);
Expand All @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -651,14 +654,21 @@ VkDevice createDevice(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, Vul
.provokingVertexLast = VK_TRUE,
};

std::vector<const char*> 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,
Expand Down Expand Up @@ -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<const char*> reqLayers;
reqLayers.reserve(1 + extensions.requiredLayers.size());

for (auto& req: extensions.requiredLayers) {
reqLayers.push_back(req.c_str());
}

std::vector<const char*> 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) {
Expand Down
4 changes: 3 additions & 1 deletion core/videoout/vulkan/vulkanSetup.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ struct SurfaceCapabilities {
};

struct VulkanObj {
std::shared_ptr<vulkan::DeviceInfo> deviceInfo = std::make_shared<DeviceInfo>();
std::shared_ptr<vulkan::DeviceInfo> deviceInfo;

VkDebugUtilsMessengerEXT debugMessenger = nullptr;
SurfaceCapabilities surfaceCapabilities;
Queues queues;

VulkanObj() { deviceInfo = std::make_shared<DeviceInfo>(); }
};

VulkanObj* initVulkan(SDL_Window* window, VkSurfaceKHR& surface, bool useValidation);
Expand Down
5 changes: 1 addition & 4 deletions modules/libkernel/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit bd26687

Please sign in to comment.