mirror of
https://github.com/thead-yocto-mirror/skia
synced 2026-07-14 12:05:24 +02:00
149 lines
4.0 KiB
C++
149 lines
4.0 KiB
C++
//
|
|
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
|
|
// Windows_system_utils.cpp: Implementation of OS-specific functions for Windows
|
|
|
|
#include "util/system_utils.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <windows.h>
|
|
#include <array>
|
|
#include <vector>
|
|
|
|
#include "util/windows/third_party/StackWalker/src/StackWalker.h"
|
|
|
|
namespace angle
|
|
{
|
|
namespace
|
|
{
|
|
static const struct
|
|
{
|
|
const char *name;
|
|
const DWORD code;
|
|
} kExceptions[] = {
|
|
#define _(E) \
|
|
{ \
|
|
# E, E \
|
|
}
|
|
_(EXCEPTION_ACCESS_VIOLATION),
|
|
_(EXCEPTION_BREAKPOINT),
|
|
_(EXCEPTION_INT_DIVIDE_BY_ZERO),
|
|
_(EXCEPTION_STACK_OVERFLOW),
|
|
#undef _
|
|
};
|
|
|
|
class CustomStackWalker : public StackWalker
|
|
{
|
|
public:
|
|
CustomStackWalker() {}
|
|
~CustomStackWalker() {}
|
|
|
|
void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry) override
|
|
{
|
|
char buffer[STACKWALK_MAX_NAMELEN];
|
|
size_t maxLen = _TRUNCATE;
|
|
if ((eType != lastEntry) && (entry.offset != 0))
|
|
{
|
|
if (entry.name[0] == 0)
|
|
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, "(function-name not available)",
|
|
_TRUNCATE);
|
|
if (entry.undName[0] != 0)
|
|
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, entry.undName, _TRUNCATE);
|
|
if (entry.undFullName[0] != 0)
|
|
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, entry.undFullName, _TRUNCATE);
|
|
if (entry.lineFileName[0] == 0)
|
|
{
|
|
strncpy_s(entry.lineFileName, STACKWALK_MAX_NAMELEN, "(filename not available)",
|
|
_TRUNCATE);
|
|
if (entry.moduleName[0] == 0)
|
|
strncpy_s(entry.moduleName, STACKWALK_MAX_NAMELEN,
|
|
"(module-name not available)", _TRUNCATE);
|
|
_snprintf_s(buffer, maxLen, " %s - %p (%s): %s\n", entry.name,
|
|
reinterpret_cast<void *>(entry.offset), entry.moduleName,
|
|
entry.lineFileName);
|
|
}
|
|
else
|
|
_snprintf_s(buffer, maxLen, " %s (%s:%d)\n", entry.name, entry.lineFileName,
|
|
entry.lineNumber);
|
|
buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
|
|
printf("%s", buffer);
|
|
OutputDebugStringA(buffer);
|
|
}
|
|
}
|
|
};
|
|
|
|
void PrintBacktrace(CONTEXT *c)
|
|
{
|
|
printf("Backtrace:\n");
|
|
OutputDebugStringA("Backtrace:\n");
|
|
|
|
CustomStackWalker sw;
|
|
sw.ShowCallstack(GetCurrentThread(), c);
|
|
}
|
|
|
|
LONG WINAPI StackTraceCrashHandler(EXCEPTION_POINTERS *e)
|
|
{
|
|
const DWORD code = e->ExceptionRecord->ExceptionCode;
|
|
printf("\nCaught exception %lu", code);
|
|
for (size_t i = 0; i < ArraySize(kExceptions); i++)
|
|
{
|
|
if (kExceptions[i].code == code)
|
|
{
|
|
printf(" %s", kExceptions[i].name);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
PrintBacktrace(e->ContextRecord);
|
|
|
|
// Exit NOW. Don't notify other threads, don't call anything registered with atexit().
|
|
_exit(1);
|
|
|
|
// The compiler wants us to return something. This is what we'd do if we didn't _exit().
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
} // anonymous namespace
|
|
|
|
void Sleep(unsigned int milliseconds)
|
|
{
|
|
::Sleep(static_cast<DWORD>(milliseconds));
|
|
}
|
|
|
|
void WriteDebugMessage(const char *format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
int size = vsnprintf(nullptr, 0, format, args);
|
|
va_end(args);
|
|
|
|
std::vector<char> buffer(size + 2);
|
|
va_start(args, format);
|
|
vsnprintf(buffer.data(), size + 1, format, args);
|
|
va_end(args);
|
|
|
|
OutputDebugStringA(buffer.data());
|
|
}
|
|
|
|
void InitCrashHandler()
|
|
{
|
|
SetUnhandledExceptionFilter(StackTraceCrashHandler);
|
|
}
|
|
|
|
void TerminateCrashHandler()
|
|
{
|
|
SetUnhandledExceptionFilter(nullptr);
|
|
}
|
|
|
|
void PrintStackBacktrace()
|
|
{
|
|
CONTEXT context;
|
|
ZeroMemory(&context, sizeof(CONTEXT));
|
|
RtlCaptureContext(&context);
|
|
PrintBacktrace(&context);
|
|
}
|
|
|
|
} // namespace angle
|