mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
Merge pull request #5957 from xXPBSXx/cand/guest-abort-report-r6
fix(libc): name a guest abort() in the crash report
This commit is contained in:
2 files changed
+35
-5
No files matched your search
@@ -381,6 +381,9 @@ LONG WINAPI ReportCrash(EXCEPTION_POINTERS* info) {
|
||||
if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && record->NumberParameters >= 2) {
|
||||
const char* kind = record->ExceptionInformation[0] == 0 ? "read" : record->ExceptionInformation[0] == 1 ? "write" : "execute";
|
||||
Report(" %s of 0x%016llx\n", kind, static_cast<unsigned long long>(record->ExceptionInformation[1]));
|
||||
std::uint8_t trap[2];
|
||||
if (record->ExceptionInformation[0] == 0 && record->ExceptionInformation[1] == ~0ull && ReadCode(context->Rip, trap, sizeof(trap)) == sizeof(trap) && trap[0] == 0xcd && trap[1] == 0x45)
|
||||
Report(" guest abort() (int 0x45)\n");
|
||||
}
|
||||
Report(" rax %016llx rbx %016llx rcx %016llx rdx %016llx\n", context->Rax, context->Rbx, context->Rcx, context->Rdx);
|
||||
Report(" rsi %016llx rdi %016llx rbp %016llx rsp %016llx\n", context->Rsi, context->Rdi, context->Rbp, context->Rsp);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
@@ -74,7 +75,7 @@ static int RunThrowChild() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
static void testUnhandledThrowSite() {
|
||||
static std::string RunChild(const wchar_t* argument, DWORD& exitCode) {
|
||||
SECURITY_ATTRIBUTES attributes{};
|
||||
attributes.nLength = sizeof(attributes);
|
||||
attributes.bInheritHandle = TRUE;
|
||||
@@ -84,7 +85,6 @@ static void testUnhandledThrowSite() {
|
||||
RequireHandle(SetHandleInformation(readPipe, HANDLE_FLAG_INHERIT, 0) != 0);
|
||||
std::array<wchar_t, 32768> image{};
|
||||
RequireHandle(GetModuleFileNameW(nullptr, image.data(), static_cast<DWORD>(image.size())) != 0);
|
||||
const wchar_t* argument = L"\" throw-uncaught";
|
||||
std::array<wchar_t, 32768> command{};
|
||||
const std::size_t imageLength = std::wcslen(image.data());
|
||||
const std::size_t argumentLength = std::wcslen(argument);
|
||||
@@ -110,22 +110,47 @@ static void testUnhandledThrowSite() {
|
||||
}
|
||||
CloseHandle(readPipe);
|
||||
RequireHandle(WaitForSingleObject(child.hProcess, 20000) == WAIT_OBJECT_0);
|
||||
DWORD exitCode = 0;
|
||||
RequireHandle(GetExitCodeProcess(child.hProcess, &exitCode) != 0);
|
||||
CloseHandle(child.hProcess);
|
||||
output[outputLength < output.size() ? outputLength : output.size() - 1] = 0;
|
||||
return std::string(output.data());
|
||||
}
|
||||
|
||||
static void testUnhandledThrowSite() {
|
||||
DWORD exitCode = 0;
|
||||
const std::string output = RunChild(L"\" throw-uncaught", exitCode);
|
||||
RequireHandle(exitCode == 0xC0000409);
|
||||
const char* probeMarker = std::strstr(output.data(), "probe ");
|
||||
const char* probeMarker = std::strstr(output.c_str(), "probe ");
|
||||
RequireHandle(probeMarker != nullptr);
|
||||
const auto probe = static_cast<std::uintptr_t>(std::strtoull(probeMarker + 6, nullptr, 16));
|
||||
RequireHandle(probe != 0);
|
||||
const char* marker = std::strstr(output.data(), "thrown from ");
|
||||
const char* marker = std::strstr(output.c_str(), "thrown from ");
|
||||
RequireHandle(marker != nullptr);
|
||||
const auto logged = static_cast<std::uintptr_t>(std::strtoull(marker + 13, nullptr, 16));
|
||||
RequireHandle(logged != 0);
|
||||
if (logged <= probe || logged - probe >= 0x1000) throw std::runtime_error("unhandled exception named the wrapper instead of the throw site");
|
||||
}
|
||||
|
||||
[[gnu::noinline, noreturn]] static void GuestAbortProbe() {
|
||||
__asm__ volatile("int $0x45");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static int RunAbortChild() {
|
||||
std::fprintf(stderr, "abort probe\n");
|
||||
std::fflush(stderr);
|
||||
GuestAbortProbe();
|
||||
}
|
||||
|
||||
static void testGuestAbortReport() {
|
||||
DWORD exitCode = 0;
|
||||
const std::string output = RunChild(L"\" guest-abort", exitCode);
|
||||
char code[16];
|
||||
std::snprintf(code, sizeof(code), "0x%08lx", static_cast<unsigned long>(exitCode));
|
||||
if (exitCode != 0xC0000005 || output.find("guest abort() (int 0x45)") == std::string::npos)
|
||||
throw std::runtime_error(std::string("guest abort child exited with ") + code + " and printed:\n" + output);
|
||||
}
|
||||
|
||||
static int destroyed;
|
||||
struct Guard { ~Guard() { ++destroyed; } };
|
||||
static void ThrowNested() {
|
||||
@@ -273,10 +298,12 @@ static void testUnwindThroughRuntimeModules() {
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1) {
|
||||
if (std::strcmp(argv[1], "throw-uncaught") == 0) return RunThrowChild();
|
||||
if (std::strcmp(argv[1], "guest-abort") == 0) return RunAbortChild();
|
||||
return 100;
|
||||
}
|
||||
TestTypeInfoVtables();
|
||||
testUnhandledThrowSite();
|
||||
testGuestAbortReport();
|
||||
testExceptionPointer();
|
||||
testFutureException();
|
||||
testMadeExceptionPointer();
|
||||
|
||||
Reference in new issue
Block a user